Go语言是一个简单却蕴含深意的语言。但是,即便号称是最简单的C语言,都能总结出一本《C陷阱与缺陷》,更何况Go语言呢。Go语言中的许多坑其实并不是因为Go自身的问题。一些错误你再别的语言中也会犯,例如作用域,一些错误就是对因为 Go 语言的特性不了解而导致的,例如 range。
其实如果你在学习Go语言的时候去认真地阅读官方文档,百科,邮件列表或者其他的类似 Rob Pike 的名人博客,报告,那么本文中提到的许多坑都可以避免。但是不是每个人都会从基础学起,例如译者就喜欢简单粗暴地直接用Go语言写程序。如果你也像译者一样,那么你应该读一下这篇文章:这样可以避免在调试程序时浪费过多时间。
var three int//error, even though it's assigned 3 on the next line
three = 3
func(unused string) {
fmt.Println("Unused arg. No compile error")
}("what?")
}
错误信息:
1
/tmp/sandbox473116179/main.go:6: one declared andnot used /tmp/sandbox473116179/main.go:7: two declared andnot used /tmp/sandbox473116179/main.go:8: three declared andnot used
/tmp/sandbox326543983/main.go:5: invalid argument m (typemap[string]int) forcap
字符串无法为 nil
级别:新手入门级
所有的开发者都可能踩的坑,在 C 语言中是可以 char *String=NULL,但是 Go 语言中就无法赋值为 nil。
错误信息:
1
2
3
4
5
6
7
8
9
package main
funcmain() {
var x string = nil//error
if x == nil { //error
x = "default"
}
}
Compile Errors:
1
/tmp/sandbox630560459/main.go:4: cannot use nil as typestring in assignment /tmp/sandbox630560459/main.go:6: invalid operation: x == nil (mismatched types string and nil)
修正代码:
1
2
3
4
5
6
7
8
9
package main
funcmain() {
var x string//defaults to "" (zero value)
if x == "" {
x = "default"
}
}
参数中的数组
Array Function Arguments
级别:新手入门级 对于 C 和 C++ 开发者来说,数组就是指针。给函数传递数组就是传递内存地址,对数组的修改就是对原地址数据的修改。但是 Go 语言中,传递的数组不是内存地址,而是原数组的拷贝,所以是无法通过传递数组的方法去修改原地址的数据的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
import"fmt"
funcmain() {
x := [3]int{1,2,3}
func(arr [3]int) {
arr[0] = 7
fmt.Println(arr) //prints [7 2 3]
}(x)
fmt.Println(x) //prints [1 2 3] (not ok if you need [7 2 3])
}
如果需要修改原数组的数据,需要使用数组指针(array pointer)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
import"fmt"
funcmain() {
x := [3]int{1,2,3}
func(arr *[3]int) {
(*arr)[0] = 7
fmt.Println(arr) //prints &[7 2 3]
}(&x)
fmt.Println(x) //prints [7 2 3]
}
或者可以使用 Slice,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
import"fmt"
funcmain() {
x := []int{1,2,3}
func(arr []int) {
arr[0] = 7
fmt.Println(arr) //prints [7 2 3]
}(x)
fmt.Println(x) //prints [7 2 3]
}
使用 Slice 和 Array 的 range 会导致预料外的结果
级别:新手入门级
如果你对别的语言中的 for in 和 foreach 熟悉的话,那么 Go 中的 range 使用方法完全不一样。因为每次的 range 都会返回两个值,第一个值是在 Slice 和 Array 中的编号,第二个是对应的数据。