图片来源于网络
Map
1、使用nil map❌
func main() {
var m map[string]int
m["one"] = 1 //error
}2、指定map容量❌
func main() {
m := make(map[string]int,99)
cap(m) //error
}3、访问map不存在的key❌
错误❌的方式
func main() {
x := map[string]string{"one":"a","two":"","three":"c"}
if v := x["two"]; v == "" { //incorrect
fmt.Println("no entry")
}
}正确✅的方式
func main() {
x := map[string]string{"one":"a","two":"","three":"c"}
if _,ok := x["two"]; !ok {
fmt.Println("no entry")
}
}4、认为遍历map是有序的
你以为他会one、two、three、four这样输出,那么你就错❌啦
func main() {
m := map[string]int{"one":1,"two":2,"three":3,"four":4}
for k,v := range m {
fmt.Println(k,v)
}
}想按顺序输出,可以参考下面??的方式
Array/Slice
1、数组函数参数
如果你想改变数组的成员,错误❌的用法
func main() {
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])
}如果你想改变数组的成员,正确✅的用法
func main() {
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]
}亦或者使用切片✅
func main() {
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]
}2、创建多维数组的正确方式✅
func main() {
x := 2
y := 4
table := make([][]int,x)
for i:= range table {
table[i] = make([]int,y)
}
}String
1.修改字符串❌
在Go语言中,String是只读的
错误❌wu的方式
func main() {
x := "text"
x[0] = 'T'
fmt.Println(x)
}正确✅的方式
func main() {
x := "text"
xbytes := []byte(x)
xbytes[0] = 'T'
fmt.Println(string(xbytes)) //prints Text
}2、索引字符串
索引字符串返回的是byte而不是整个字符
func main() {
x := "我text"
fmt.Println(x[0]) //print 230
fmt.Println(string(x[0])) //print æ
fmt.Printf("%T",x[0]) //prints uint8
}如果想要想访问整个字符使用 for range
func main() {
x := "我text"
for _,v := range x {
fmt.Printf("%c",v) //prints uint8
}
}3、字符串的长度
当我们想统计字符串的长度的时候
使用len去统计字符串长度的时候会懵逼❌
func main() {
data := "♥"
fmt.Println(len(data)) //prints: 3
}正确✅统计字符串长度的方式
func main() {
data := "♥"
fmt.Println(utf8.RuneCountInString(data)) //prints: 1
}Int
1、自增和自减
在很多都会支持++i和i++这种方式的自增或者自减
Go语言中不支持++i这种前缀自增和自减方式,也不能按照下面的方式使用
func main() {
data := []int{1,2,3}
i := 0
++i //error
fmt.Println(data[i++]) //error
}Goroutine
1、程序不会等待所有Goroutine结束
错误❌的方式
func main() {
workerCount := 2
for i := 0; i < workerCount; i++ {
go doit(i)
}
time.Sleep(1 * time.Second)
fmt.Println("all done!")
}
func doit(workerId int) {
fmt.Printf("[%v] is running\n",workerId)
time.Sleep(3 * time.Second)
fmt.Printf("[%v] is done\n",workerId)
}你会看到
[0] is running
[1] is running
all done!
因为在Go中,并不会等待所有goroutine运行结束,程序才会结束
如果想等待所有goroutine运行结束,才结束程序,那么得使用sync.WaitGroup
看下正确✅的姿势
func main() {
var wg sync.WaitGroup
workerCount := 2
for i := 0; i < workerCount; i++ {
wg.Add(1)
go doit(i,&wg)
}
wg.Wait()
fmt.Println("all done!")
}
func doit(workerId int,wg *sync.WaitGroup) {
fmt.Printf("[%v] is running\n",workerId)
defer wg.Done()
fmt.Printf("[%v] is done\n",workerId)
}正常的输出
[1] is running
[1] is done
[0] is running
[0] is done
all done!
Channel
1、向已经关闭的chan发送数据
func main() {
ch := make(chan int)
for i := 0; i < 3; i++ {
go func(idx int) {
ch <- (idx + 1) * 2
}(i)
}
//get the first result
fmt.Println(<-ch)
close(ch) //not ok (you still have other senders)
//do other work
time.Sleep(2 * time.Second)
}2、nil chan发送或接收数据
func main() {
var ch chan int
for i := 0; i < 3; i++ {
go func(idx int) {
ch <- (idx + 1) * 2
}(i)
}
//get first result
fmt.Println("result:",<-ch)
//do other work
time.Sleep(2 * time.Second)
}References
50 Shades of Go: Traps, Gotchas, and Common Mistakes for New Golang Devs
版权声明:本文为qq_37186127原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。
