go vet - 循环变量i由func literal捕获。

问题描述 投票:1回答:1

在下面的代码中。

package main

import "fmt"

func main() {
    for i := 0; i <= 9; i++ {
        go func() {
            fmt.Println(i)
        }()
    }
}

输出:

code$ 
code$ go install github.com/myhub/cs61a
code$ bin/cs61a 
code$ 

上面的程序没有提供任何输出。

1) 单个内存位置是否存在数据竞赛?i 中的10个执行程序?

2) 为什么上面的代码没有打印自由变量的值?i?

loops go concurrency goroutine
1个回答
2
投票

是否存在数据竞赛?

是的,通过运行 go run -race example.go. 主goroutine写道 i,而其他goroutines读取它时不需要任何同步。参见 将参数传递给函数闭合; 为什么这两个for循环的变化会给我不同的行为?使用循环slicesmap的范围注册多个路由。.

为什么上面的代码没有任何打印?

因为当主程序结束时,你的程序也结束了。它不会等待其他非main goroutines来完成。见 goroutine没有输出

修复

复制一个循环变量,并在闭包中使用该变量,并使用一个 sync.WaitGroup 来等待启动的goroutines结束。

var wg sync.WaitGroup
for i := 0; i <= 9; i++ {
    i2 := i
    wg.Add(1)
    go func() {
        defer wg.Done()
        fmt.Println(i2)
    }()
}
wg.Wait()

这将输出(在 去游乐场):

9
0
2
1
6
5
3
7
8
4

另一个办法是通过 i 作为启动函数的参数。

var wg sync.WaitGroup
for i := 0; i <= 9; i++ {
    wg.Add(1)
    go func(i int) {
        defer wg.Done()
        fmt.Println(i)
    }(i)
}
wg.Wait()

试试这个 去游乐场.

© www.soinside.com 2019 - 2024. All rights reserved.