matched = append(matched, w)
Это критическая секция , которая не синхронизирована , что приводит к состоянию гонки. Это не операция атома c. Есть много разных промежуточных элементов в подпрограммах go, которые приведут к разным выходам, и абсолютно непредсказуемы с возможностью потери данных.
Самый простой способ сделать этот поточно-безопасный (безопасный для одновременного выполнения) предназначен для синхронизации доступа к matched
с мьютексом :
func goRoutinesSearch(body string, keywords []string) {
lowerBody := strings.ToLower(body)
var mutex = &sync.Mutex{}
var matched []string
var wg sync.WaitGroup
wg.Add(len(keywords))
for _, word := range keywords {
go func(w string) {
defer wg.Done()
if strings.Contains(lowerBody, w) {
mutex.Lock()
matched = append(matched, w)
mutex.Unlock()
}
}(word)
}
wg.Wait()
fmt.Print(matched)
}
Мьютекс гарантирует, что только одна подпрограмма go способна * От 1016 * до matched
в любой момент времени, поэтому у вас никогда не будет перезаписывающих добавок.
Я думаю, что вы все равно можете иметь разные результаты массива в зависимости от порядка выполнения goroutines, но вы не потеряете данные теперь, когда они синхронизированы.