2020年4月底入职Tencent CSIG,自此由Java转Go。此时Go最新版是1.14.2,我学习参考的书籍是《Go语言学习笔记》,此书基于Go1.6。
Go是一个非常年轻的编程语言,2012年才发布第1个版本。而Java就比较古老了,1995年发布。
go语句结束后不用分号。入口函数func main()没有参数,必须放在main包中package main,文件名不必要是main.go。
使用var定义变量:
var x int32
var x = 100
x := 100
一次可以定义多个变量:
a, b := 1, 2
if后面的条件表达式不加括号:
if x > 0 {
}
if后面还可以跟两段式的条件,如
if result, err := getPatientsFromDb(); err != nil {
} else {
}
for循环也不加括号:
for i := 0; i < 10; i++ {
}
注意,在for循环的循环条件中定义临时变量时,只能用var省略的方式,否则会报编译错误。
for死循环:
for {
}
或者
for true {
}
for...range语法:
x := []int{100, 101, 102}
for i, n:= range x {
println(i, "=", n)
}
在go中,只有for循环,没有while循环,但是可以用for来像while循环那样写,如下:
x := 0
for x < 5 {
println(x)
x++
}
函数可以有多个返回值:
func div(a int, b int) (int, error) { if b == 0 { return 0, errors.New("division by zero") } return a / b, nil }
返回值有多个的话,返回值类型需要用括号括住。
函数可以有不定长入参,但要求参数类型是一样的
func sum(p ...int) int { a := 0 for _, n := range p { a = a + n } return a }
不定长入参,参数类型用3个点加数据类型表示,如...string,...int32,参数用作slice使用(判断依据是可以作为append函数的第一个参数)。注意,不定长入参必须是最后一个参数(如果还有其他类型的参数,则不定长入参要放到最后),否则会报编译错误。这也说明了只能有一个不定长入参。
在函数中,可以用defer定义延迟调用,效果等同于java的finally块:
func main() { defer println("abc") str := "amy" var a = str[0:4] println(a) }
上面函数中,虽然str[0:4]会报错,但是还是会打印出abc。像数组和slice的截取一样,字符串截取也用中括号和冒号。
string[start:end]:截取字符串从索引start开始到索引end结束区间的字符串。
start表示要截取的第一个字符所在的索引(包含)。如果不指定,默认为0,也就是从字符串的开头截取。
end表示要截取的最后一个字符所在的索引(不包含)。如果不指定,默认为字符串的长度。
panic就相当于java中的throw Exception,panic后面的语句是不可达的
func sum() int { defer println("abc") panic("err") return 0 }
在go中,控制循环,除了常规的break、continue外,多了一个goto,配合label使用,如下
func main() { for i := 1; i < 10; i++ { for j := 1; j < 10; j++ { if j > 1 { goto flag } fmt.Println("i= " + strconv.Itoa(i) + ", j= " + strconv.Itoa(j)) } } flag: fmt.Println("OK") }
goto后面跟一个label,当执行到goto行时,直接跳到后面的label行,执行下一行代码,不管goto行嵌在多少层循环中。
使用const定义常量
如const MONDAY int32 = 1
和变量不同,常量在定义后不使用不会报编译错误。
如果要一次定义多个常量,则可以使用const块。在const块中,如果常量没有用等号赋值,那么将沿用上一行的赋值等式,如下
func main() { const ( a = "A" b ) fmt.Println(a) fmt.Println(b) }
常量a赋值为字符串"A",常量b没有用等号赋值,那么将沿用上一行的赋值等式,即b = "A",所以b值也为字符串"A"。
iota使用
iota用在const块中,初始值是0,每新定义一个变量iota值就加1,直到遇见新的const,iota变为0。
func main() { const ( a int = iota b ) const ( c int = iota d int = iota ) fmt.Println(a) fmt.Println(b) fmt.Println(c) fmt.Println(d) }
常量a由iota赋值,此时iota值为0,故a值为0。给a赋值后,iota变为1,又赋值给b,故b值为1。在新的const块中,iota变为0,同理可知,c值为0,d值为1。
os.Args用于获取命令行参数,返回值是个数组。
如执行go run hello_world.go a b c d e,则打印os.Args会把a b c d e打印出来。
go不支持隐式类型转换,别名和原有类型也不能进行隐式类型转换,会报编译错误。
获取int32、int64的最大值:math.MaxInt32、math.MaxInt64。