for...range内でgoroutineを起動する場合注意すること
5431 ワード
結論
for...range
で取り出した値をgoroutineで使用する場合は関数の引数経由で参照する
実験
以下のようにfor...range
で取り出した値をクロージャ内でそのまま参照すると、意図したものとは別のデータが参照されてしまう。
これはgoroutineの起動よりも早くループが回ってしまうために、クロージャ内では毎回tasks
の最後の値が参照されてしまっている。
package main
import (
"fmt"
"time"
)
func main() {
tasks := []string{
"first!",
"second!!",
"third!!!",
}
for _, task := range tasks {
go func() {
fmt.Println(task)
}()
}
time.Sleep(time.Second)
}
$ go run main.go
third!!!
third!!!
third!!!
以下のように引数経由で参照すれば解決できる。
package main
import (
"fmt"
"time"
)
func main() {
tasks := []string{
"first!",
"second!!",
"third!!!",
}
for _, task := range tasks {
go func(task string) {
fmt.Println(task)
}(task)
}
time.Sleep(time.Second)
}
$ go run main.go
first!
second!!
third!!!
Author And Source
この問題について(for...range内でgoroutineを起動する場合注意すること), 我々は、より多くの情報をここで見つけました https://zenn.dev/morris/articles/abc085c17c6355著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol