https://github.com/teivah/100-go-mistakes#table-of-contents
nil Map
map记得要make初始化, slice可以不用初始化!
func main() {
var course map[string]string
course["name"] = "go体系课"
}
结构体空指针
空结构体和结构体空指针可不一样
type Course struct {
Name string
Desc string
}
func (c *Course) String() float64 {
return c.Name + c.Desc
}
func main() {
var c *Course
fmt.Println(c.String())
}
使用对循环迭代器变量的引用 - 大坑!
在 Go 中,循环迭代器变量是一个单一的变量,在每个循环迭代中取不同的值。这如果使用不当,可能会导致非预期的行为。
func main() {
var out []*int
for i := 0; i < 3; i++ {
out = append(out, &i)
}
fmt.Println("Values:", *out[0], *out[1], *out[2])
fmt.Println("Addresses:", out[0], out[1], out[2])
}
解决办法
func main() {
var out []*int
for i := 0; i < 3; i++ {
tmpi := i
out = append(out, &tmpi)
}
fmt.Println("Values:", *out[0], *out[1], *out[2])
fmt.Println("Addresses:", out[0], out[1], out[2])
}
原因是:在每次迭代中,我们将 i 的地址追加到 out 切片中,但由于它是同一个变量,我们实际上追加的是相同的地址,该地址最终包含分配给 i 的最后一个值。
所以只需要拷贝一份,让两者脱离关联就可以了。
同样的,如果这里是for循环然后启动多个goroutine, 如下:
package main
import (
"fmt"
"strconv"
"time"
)
func main() {
goodsID := []uint64{1, 2, 3, 4, 5}
for _, id := range goodsID {
go func() {
fmt.Println("正在查询商品:" + strconv.Itoa(int(id)))
}()
}
time.Sleep(time.Second * 5)
}
注意:这种bug在goland中一般会提醒,
常用的解决办法:
package main
import (
"fmt"
"strconv"
"time"
)
func main() {
goodsID := []uint64{1, 2, 3, 4, 5}
for _, id := range goodsID {
go func(id uint64) {
fmt.Println("正在查询商品:" + strconv.Itoa(int(id)))
}(id)
}
time.Sleep(time.Second * 5)
}