Как было объявлено, можно передать значения в качестве параметров функции в функцию goroutine.
Или можно использовать метод создания явных переменных в области действия циклов. Для простоты вы можете использовать одно и то же имя переменной. Это гарантирует, что подпрограмма ссылается на значение закрытия цикла for (а не на динамическое значение внешней области действия, которое вы испытывали):
for _, originIata := range originCities {
originIata := originIata // here
for _, destinationIata := range destinationCities {
destinationIata := destinationIata // here
go func () {
fmt.Println(originIata)
fmt.Println(destinationIata)
wg.Done()
}()
}
}
Примечание: указанное выше исправление будет работать, только если копии сделаны за пределами функции goroutine.
Редактировать: использовать инструменты go, такие как go vet
, и детектор гонки go , чтобы помочь поймать эти gotcha ошибки типа.
Например, игровая площадка go (а также популярные редакторы, такие как VScode) по умолчанию запускают go vet
, например,
https://play.golang.org/p/JhALssCu2-T
Но обратите внимание, не не полагается на go vet
в качестве защитного покрытия. На игровой площадке выше не ловит внешнее o
потенциальное состояние гонки.
Вы можете создать свой исполняемый файл с помощью детектора гонки данных (tl;dr; go build -race
; используйте это для тестирования, а не для производства - так как он работает медленнее и имеет что-то вроде предела стандартной процедуры 8K).
Детектор гонки распознает только проблемы с гонками данных во время выполнения . Поэтому используйте его разумно, так как он не является анализатором потока кода и поэтому не может предсказать какие-либо будущие потенциальные проблемы с выполнением кода.