一個go閉包使用上的小坑

一個go閉包使用上的小坑


無意間看到這樣一串代碼:

m := make(map[int]int, 10)
for i := 1; i<= 10; i++ {
    m[i] = i
}

for k, v := range(m) {
    go func() {
        fmt.Println("k ->", k, "v ->", v)
    }()

好奇 跑了一下:

go run tmp.go 
k -> 7 v -> 7
k -> 7 v -> 7
k -> 7 v -> 7
k -> 4 v -> 4
k -> 7 v -> 7
k -> 7 v -> 7
k -> 7 v -> 7
k -> 7 v -> 7
k -> 7 v -> 7
k -> 7 v -> 7

可以看到 go閉包裏頭併發的使用外部自由變量後,輸出的結果出乎意料是錯亂的,

這說明這種情形,應該是用傳參的方式,而非引用外部變量

修改方法兩種:
1.傳參

m := make(map[int]int, 10)
for i := 1; i<= 10; i++ {
    m[i] = i
}

for k, v := range(m) {
    go func(k, v int) {
        fmt.Println("k ->", k, "v ->", v)
    }(k, v)
}

2.串行執行

m := make(map[int]int, 10)
for i := 1; i<= 10; i++ {
    m[i] = i
}

for k, v := range(m) {
    func() {
        fmt.Println("k ->", k, "v ->", v)
    }()
}
go run tmp.go 
k -> 1 v -> 1
k -> 6 v -> 6
k -> 10 v -> 10
k -> 2 v -> 2
k -> 3 v -> 3
k -> 4 v -> 4
k -> 5 v -> 5
k -> 7 v -> 7
k -> 8 v -> 8
k -> 9 v -> 9

最近準備溫習一下golang,空了會更新下學習協程,gc,常用引用底層實現相關的內容,感興趣可以關注下我哦~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章