前言
這是Go十大常見錯誤系列的第10篇:Goroutine和迴圈變數一起使用的坑。素材來源於Go佈道者,現Docker公司資深工程師Teiva Harsanyi。
本文涉及的原始碼全部開源在:Go十大常見錯誤原始碼,歡迎大家關注公眾號,及時獲取本系列最新更新。
常見錯誤
對於Go初學者,很容易犯的一個錯誤就是goroutine和迴圈變數結合在一起使用時,錯誤地使用了迴圈變數。
比如下面這個例子:
ints := []int{1, 2, 3}
for _, i := range ints {
go func() {
fmt.Printf("%v\n", i)
}()
}
這段程式的輸出結果應該是什麼?
Go初學者可能認為輸出結果應該是1 2 3
,但實際情況並不是。
這個例子裡,3個goroutine共享同一個變數i
,最後輸出的結果大機率是輸出3 3 3
。
要解決這個問題,主要有2個解決方案。
解決方案1
把迴圈變數i
作為goroutine函式的一個引數,編譯器在執行go func(i int)
時,就會解析到i
的值,確保每個goroutine可以拿到自己想要的值。
ints := []int{1, 2, 3}
for _, i := range ints {
go func(i int) {
fmt.Printf("%v\n", i)
}(i)
}
解決方案2
建立一個新的變數,用於goroutine。
ints := []int{1, 2, 3}
for _, i := range ints {
i := i
go func() {
fmt.Printf("%v\n", i)
}()
}
推薦閱讀
- Go十大常見錯誤第1篇:未知列舉值
- Go十大常見錯誤第2篇:benchmark效能測試的坑
- Go十大常見錯誤第3篇:go指標的效能問題和記憶體逃逸
- Go十大常見錯誤第4篇:break操作的注意事項
- Go十大常見錯誤第5篇:Go語言Error管理
- Go十大常見錯誤第6篇:slice初始化常犯的錯誤
- Go十大常見錯誤第7篇:不使用-race選項做併發競爭檢測
- Go十大常見錯誤第8篇:併發程式設計中Context使用常見錯誤
- Go面試題系列,看看你會幾題?
開源地址
文章和示例程式碼開源在GitHub: Go語言初級、中級和高階教程。
公眾號:coding進階。關注公眾號可以獲取最新Go面試題和技術棧。
個人網站:Jincheng's Blog。
知乎:無忌。
福利
我為大家整理了一份後端開發學習資料禮包,包含程式語言入門到進階知識(Go、C++、Python)、後端開發技術棧、面試題等。
關注公眾號「coding進階」,傳送訊息 backend 領取資料禮包,這份資料會不定期更新,加入我覺得有價值的資料。還可以傳送訊息「進群」,和同行一起交流學習,答疑解惑。