这几天在复现之前比赛时发现go的出现频率越来越高了,所以借此也潜学一下go。个人学习笔记,由于有一丢丢的语言基础所以写的比较浅显。(写完这篇期末了 咕咕几天)
环境配置 开发环境Downloads - The Go Programming Language (google.cn)
下载后选择路径安装即可
go verion查看版本
Go ModGolang 无法下载依赖解决方案,需要翻墙才能下载。Go 1.11 版本开始,官方支持了 go module 包依赖管理工具。其实还新增了 GOPROXY
环境变量。如果设置了该变量,下载源代码时将会通过这个环境变量设置的代理地址,而不再是以前的直接从代码库下载。这无疑对我等无法科学上网的程序员来说是最大的福音。更可喜的是,https://goproxy.io/
这个开源项目帮我们实现好了我们想要的。该项目允许开发者一键构建自己的 GOPROXY 代理服务。同时,也提供了公用的代理服务
https://goproxy.io,我们只需设置该环境变量即可正常下载被墙的源码包了:
设置
set GO111MODULE=on set GOPROXY=https://goproxy.io go env //运行结束后查看是否配置成功开发工具
我用的是jetbrains的Goland,用VScode也可以
Download GoLand: A Go IDE with extended support for JavaScript, TypeScript, and databases (jetbrains.com)
设置GOROOT和GOPATH即可
第一个程序用Goland创建项目后会自动生成go.mod,如果不是通过项目创建的则可以通过命令创建go.mod文件
go mod init 文件夹名称
Hello, world!
package main
import "fmt"
func main() {
fmt.Println("Hello, world!")
}
结果
运行后控制台一直出现多余信息,将它折叠掉
Ctrl+Shift+V 输入Registry 将go.run.process.with.pty取消勾选即可变量
Go语言中的变量需要声明后才能使用,并且变量声明后必须使用
变量声明 语法声明变量的一般形式是使用 var 关键字var identifier type
var name string var age int var b bool批量声明
var( name string age int b bool )变量的初始化 语法
var 变量名 类型 = 表达式
例
var name string = "Sentiment" var age int = 18 var b bool = true类型推导
在声明变量时,可以根据初始化的值进行类型推到,从而省略类型声明
var name = "Sentiment" var age = 18 var b = true批量初始化
var name, age, b = "Sentiment", 18, true短变量声明
在函数内部,可以使用:=运算符进行变量声明及其初始化
name:="Sentiment" age:=18 b:=true匿名变量
可以接收多个变量,如果有些变量用不到则可用_代替变量名
package main
import "fmt"
func test() (string, int, bool) {
return "Sentiment", 18, true
}
func main() {
name, age, _ := test()
fmt.Println(name)
fmt.Println(age)
}
常量
常量声明
语法
const 常量名 类型 = 表达式
例
package main
import "fmt"
func main() {
const age int = 18 //常规语法
const PI = 3.14 //可以省略类型
const (
name = "Sentiment"
b = true
)
const x, y = 1, 2 //批量赋值
fmt.Println(age)
}
同时声明多个常量时,若为赋初值则默认与上方赋值相同
package main
import "fmt"
func main() {
const (
x = 100
y
z
)
fmt.Printf("x=%vn", x)
fmt.Printf("y=%vn", y)
fmt.Printf("z=%vn", z)
}
结果:
x=100 y=100 z=100iota
iota可以被认为是一个可编辑器修改的常量,默认值为0,每调用一次+1
package main
import "fmt"
func main() {
const (
x = iota
y = iota
z = iota
)
fmt.Printf("x=%vn", x)
fmt.Printf("y=%vn", y)
fmt.Printf("z=%vn", z)
}
结果:
x=0 y=1 z=2
可以通过_跳过某个值
package main
import "fmt"
func main() {
const (
x = iota
_
z = iota
)
fmt.Printf("x=%vn", x)
fmt.Printf("z=%vn", z)
}
结果:
x=0 z=2
iota插队
package main
import "fmt"
func main() {
const (
x = iota
y = 100
z = iota
)
fmt.Printf("x=%vn", x)
fmt.Printf("y=%vn", y)
fmt.Printf("z=%vn", z)
}
结果:
x=0 y=100 z=2
感觉没啥应用场景,去找了一下参考参考就行Golang iota 标识符应用教程_梦想画家的博客-CSDN博客_golang itoa
输入 Scan当使用Scan输入完成后,会得到两个值:
- count:用户输入值的个数
- err:用户输入的错误信息
package main
import "fmt"
func main() {
var name string
var age int
fmt.Println("请输入用户名:")
count, err := fmt.Scan(&name, &age)
fmt.Println(count, err)
fmt.Printf("用户名为:%s", name)
}
age 为int型若输入错误,则会返回error信息
注:若scan设置了两个参数,则需要两个值都传完才能停止运行,否则会一直等待
Scanln与Scan的区别在于,回车后就会停止,无论两个值是否传完。
Scanf支持格式符输入
fmt.Println("请输入用户名:")
fmt.Scanf("name:%s", &name)
fmt.Println(name)
但这种方式有个问题如果在格式符后输入同类型字符,go语言则无法正常解析截断部分
把格式符后边加上age
fmt.Scanf("name:%sage", &name)
可以看到根据格式输入了age,但并没有截断而是一并输出了
这个问题可以用空格分割解决
fmt.Scanf("name:%s age", &name)
数据类型
基本数据类型
布尔型
var b bool
整型
int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64
uint代表无符号型
var a uint
var b uint8
var c int
fmt.Printf("%Tn", a)
fmt.Printf("%Tn", b)
fmt.Printf("%Tn", c)
结果
uint uint8 int
浮点型
float32, float64
复数型
complex64, complex128
字符串型
string
派生数据类型数组型
var arr [3]int = [3]int{1, 2, 3}
fmt.Printf("%Tn", arr)
结果
[3]int
切片型
感觉就是个可变长数组
var arr []int = []int{1, 2, 3}
fmt.Printf("%Tn", arr)
结果
[]int
指针型
a := 100
p := &a
fmt.Printf("%T", p)
结果
*int
函数型
func a() {
}
func main() {
fmt.Printf("%T", a)
}
结果
func()
还有很多其他类型学到在记吧
字符串 定义方式主要分为这几种方式,多行定义时用反引号``
var s string = "Sentiment"
var s1 = "Tana"
s2 := "Shelter"
s3 := `
Sentiment
Tana
Shelter
`
fmt.Printf("s:%vn", s)
fmt.Printf("s1:%vn", s1)
fmt.Printf("s2:%vn", s2)
fmt.Printf("s3:%vn", s3)
结果
s:Sentiment s1:Tana s2:Shelter s3: Sentiment Tana Shelter字符串拼接 加号拼接
跟python一样
var s string = "Sentiment"
var s1 = "Tana"
s2 := s + " " + s1
fmt.Printf("s2:%vn", s2)
结果
s2:Sentiment Tanafmt.Sprintf()
var s string = "Sentiment"
var s1 = "Tana"
s2 := fmt.Sprintf("%s,%s", s, s1)
fmt.Printf("s2:%vn", s2)
结果
s2:Sentiment,Tanastrings.Join()
var s string = "Sentiment"
var s1 = "Tana"
s2 := strings.Join([]string{s, s1}, ",")
fmt.Printf("s2:%vn", s2)
结果
s2:Sentiment,Tanabuffer.WriteString()
var s bytes.Buffer
s.WriteString("Sentiment")
s.WriteString(",")
s.WriteString("Tana")
fmt.Printf("s2:%vn", s.String()) //注:这里用的是s.String(),否则输出的是十进制
结果
s2:Sentiment,Tana切片操作
str := "Sentiment,Tana" n := 10 m := 14 fmt.Println(str[n]) //获取字符串索引为n的字符十进制数 fmt.Println(str[n:m]) //截取n 到 m-1 的字符串 fmt.Println(str[n:]) //从n截取到结束 fmt.Println(str[:m]) //从0截取到 m-1处
结果
84 Tana Tana Sentiment,Tana字符串常用方法
简单试几个方法,剩下的看feng师傅总结的就行
str := "Sentiment,Tana" fmt.Println(len(str)) fmt.Println(strings.Split(str, ",")) fmt.Println(strings.Contains(str, "Tana")) fmt.Println(strings.HasPrefix(str, "Sentiment")) fmt.Println(strings.HasSuffix(str, "Tana")) fmt.Println(strings.Index(str, "ment"))
结果
14 [Sentiment Tana] true true true 5
feng师傅总结的方法
strings.HasPrefix(s string, prefix string) bool //判断s是否以prefix开头 strings.HasSuffix(s string, suffix string) bool //判断s是否以suffix结尾 strings.Contains(s string, substr string) bool //判断s中是否包含substr strings.Index(s string, str string) int //返回str在s中的第一个索引,-1表示s不包含str strings.LastIndex(s string, str string) int //返回str在s中的最后一个索引,-1表示s不包含str strings.IndexRune(s string, r rune) int //同上,只不过如果r是非ASCII编码的字符的话。 strings.Replace(str, old, new, n) string //用于将字符串 str 中的前 n 个字符串 old 替换为字符串 new,并返回一个新的字符串,如果 n = -1 则替换所有字符串 old 为字符串 new strings.Count(s, str string) int //计算字符串 str 在字符串 s 中出现的非重叠次数。非重叠的意思是,比如s是egoegoegoego,str是egoego,则Count得到的返回值是2 strings.Repeat(s, count int) string //重复 count 次字符串 s 并返回一个新的字符串 strings.ToLower(s) string //将字符串中的 Unicode 字符全部转换为相应的小写字符 strings.ToUpper(s) string //将字符串中的 Unicode 字符全部转换为相应的大写字符 strings.TrimSpace(s string) string //去除字符串开头和结尾的空白符号 strings.Trim(s string, cutset string) string //去除字符串开头和结尾的cutset字符串。 strings.TrimLeft(s string, cutset string) string //去除字符串开头的cutset字符串 strings.TrimRight(s string, cutset string) string //去除字符串结尾的cutset字符串 strings.Fields(s string) []string //利用空白作为分隔符将字符串分割为若干块,并返回一个 slice 。如果字符串只包含空白符号,返回一个长度为 0 的 slice strings.Split(s string, sep string) []string //利用sep作为分隔符将字符串分割为若按块,并返回一个slice strings.Join(sl []string, sep string) string //将元素类型为 string 的 slice 使用分割符号来拼接组成一个字符串格式化输出 占位符
基本占位符
(%v、%+v、%#v、%T)
type Test struct {
Name string
}
func main() {
var name = Test{Name: "Sentiment"}
fmt.Printf("%vn", name) //输出值
fmt.Printf("%+vn", name) //先输出字段类型,再输出该字段的值
fmt.Printf("%#vn", name) //先输出结构体名字值,再输出结构体(字段类型+字段的值)
fmt.Printf("%T", name) //输出变量类型
}
结果:
{Sentiment}
{Name:Sentiment}
main.Test{Name:"Sentiment"}
main.Test
布尔占位符
(%t)
var b bool = true
fmt.Printf("%t", b) //输出布尔值true或false
整数占位符
%b 二进制表示 %c 相应Unicode码点所表示的字符 %d 十进制表示 %o 八进制表示 %q 单引号围绕的字符字面值,由Go语法安全地转义 %x 十六进制表示,字母形式为小写 a-f %X 十六进制表示,字母形式为大写 A-F %U Unicode格式:U+1234,等同于 “U+%04X”
a := 105
b := 222
fmt.Printf("%bn", a) //二进制
fmt.Printf("%cn", a) //字符
fmt.Printf("%dn", a) //十进制
fmt.Printf("%on", a) //八进制
fmt.Printf("%qn", a) //单引号转义
fmt.Printf("%xn", b) //十六进制小写形式
fmt.Printf("%Xn", b) //十六进制大写形式
fmt.Printf("%Un", a) //Unicode格式,等价于"U+%04X"
结果
1101001 i 105 151 'i' de DE U+0069
字符串与字节切片
%s 输出字符串表示(string类型或[]byte) %q 双引号围绕的字符串,由Go语法安全地转义 %x 十六进制,小写字母,每字节两个字符 %X 十六进制,大写字母,每字节两个字符
name := "Sentiemnt"
name1 := []byte("Tana")
fmt.Printf("%sn", name1) //字节型
fmt.Printf("%qn", name) //双引号围绕
fmt.Printf("%xn", name) //小写十六进制
fmt.Printf("%Xn", name) //大写十六进制
结果:
Tana "Sentiemnt" 53656e7469656d6e74 53656E7469656D6E74
指针占位符
(%p)
name := "Sentiemnt"
p := &name
fmt.Printf("%p", p) //指针型
结果
0xc00004c250运算符
跟其它语言都一样
算数运算符
+、-、*、/、%、++、–
赋值运算符
=、+=、-=、*=、/=、%=、<<=、>>=、&=、^=、!=
关系运算符
==、!=、>、<、>=、<=
逻辑运算符
!、&&、||
位运算符
<<、>>、&、|、!



