英文:
In Go, How to concurrently append to slice with filtering while preserving the order and no data race
问题
你好,这是我的示例Go Playground链接:https://go.dev/play/p/dUUsf6OXt1x
input := []int{1, 2, 3, 4, 5, 6, 7, 8}
wg := sync.WaitGroup{}
var result []int
for i, num := range input {
wg.Add(1)
go func(num, i int) {
if num%2 == 0 {
result = append(result, num)
}
wg.Done()
}(num, i)
}
wg.Wait()
fmt.Println(result)
我的目标是以正确的顺序得到结果 2,4,6,8。
不幸的是,由于我使用的是追加操作而不是分配给特定切片索引,有时会丢失数据(由于数据竞争),并以不正确的顺序接收结果。
问题在于输入是动态的,它具有无限数量的值,我不知道有多少输入的值无法通过 num%2 == 0
的过滤。
请问你能指导我如何在保持顺序的同时并发地追加筛选结果并保存所有数据吗?
英文:
Hello here's my sample go playground https://go.dev/play/p/dUUsf6OXt1x
input := []int{1, 2, 3, 4, 5, 6, 7, 8}
wg := sync.WaitGroup{}
var result []int
for i, num := range input {
wg.Add(1)
go func(num, i int) {
if num%2 == 0 {
result = append(result, num)
}
wg.Done()
}(num, i)
}
wg.Wait()
fmt.Println(result)
My goal result : 2,4,6,8 in the right order
Unfortunately on my code because I am appending instead of assigning to specific slice index, I sometimes lose data (due to data race) and receive the result in an improper order.
The problem is the input is dynamic, it has a limitless count and I have no idea how many of the values of input will not pass the filtering of num%2 == 0
Can you please guide me how to concurrently append the filtered result while preserving the order and all of data
答案1
得分: 1
根据@mkopriva的建议,我通过以下方式解决了这个问题:
不幸的是,我有两个循环而不是一个,而且我不能与第二个循环并发,因为我会遇到与第一个循环相同的问题。
events := []int{1, 2, 3, 4, 5, 6, 7, 8}
channels := make([]chan *int, 0)
// 并发开始
for _, event := range events {
channel := make(chan *int)
go response(event, channel)
channels = append(channels, channel)
}
// 收集响应
var response []int
for i := range channels {
result := <-channels[i]
if result%2 == 0 {
response = append(response, result)
}
}
// 打印响应
log.Printf("channel response %v", response)
Go playground: https://go.dev/play/p/gW7nNireNLS
嗯,这是最好的方式吗?
英文:
Based on @mkopriva's suggestion
I solve this by the ff :
Unfortunately I have 2 loops instead of 1 and I cannot concurrent with the 2nd one because I will have the same problem as the first one.
events := []int{1, 2, 3, 4, 5, 6, 7, 8}
channels := make([]chan *int, 0)
// start concurrently
for _, event := range events {
channel := make(chan *int)
go response(event, channel)
channels = append(channels, channel)
}
// collect response
var response []int
for i := range channels {
result := *<-channels[i]
if result%2 == 0 {
response = append(response, result)
}
}
// print response
log.Printf("channel response %v", response)
Go playground: https://go.dev/play/p/gW7nNireNLS
Hmmmm is this the best way?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论