go vet - l oop переменная, полученная с помощью fun c literal - PullRequest
0 голосов
/ 06 мая 2020

В приведенном ниже коде:

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 go -программ?

2) Почему приведенный выше код не печатает значение свободной переменной i?

1 Ответ

3 голосов
/ 06 мая 2020

Есть ли гонка данных?

Да, подтвердите это, запустив go run -race example.go. Основная горутина записывает i, а другие горутины читают его без какой-либо синхронизации. См. Передача параметров в закрытие функции ; Почему эти два варианта для l oop дают мне разное поведение? и Зарегистрируйте несколько маршрутов, используя диапазон для l oop срезов / карты .

Почему приведенный выше код ничего не печатает?

Потому что, когда заканчивается основная горутина, ваша программа также завершается. Он не ждет, пока другие горутины, отличные от main, завершат sh. См. Нет вывода из горутины

Исправить

Сделайте копию переменной l oop и используйте ее в замыканиях, а sync.WaitGroup подождите для завершения запущенных горутин:

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()

Это будет выводить (попробуйте на Go Playground ):

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()

Попробуйте это на Go Playground .

...