从切片中同时删除
Deleting concurrently from a slice
我有一个数组 X,我正在尝试对它进行范围调整并在条件为真时删除一些元素。
在没有任何并发的情况下执行此操作很好,但是当我尝试同时执行此操作时,出现错误:
“切片边界超出范围”
func main() {
X := make([][]int32, 10)
for i := 0; i < 10; i++ {
X[i] = []int32{int32(i), int32(i)}
}
ch := make(chan int, 20)
var wg sync.WaitGroup
fmt.Println(X)
for i := 0; i < 20; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for index := range X {
// check some condition
if X[index][0]%2 == 0 && index < len(X)-1 {
ch <- index
break
}
}
}()
}
for {
ind, ok := <-ch
if ok {
X = append(X[:ind], X[ind+1:]...)
} else {
fmt.Println("closed chan")
break
}
}
wg.Wait()
fmt.Println(X)
}
https://play.golang.org/p/YeLamAU5_Rt
有没有办法使用索引并通过通道发送它,然后从不同的 goroutine 中删除相应的元素?
将要保留的元素复制到切片的开头。删除 goroutines。
keep := 0
for index := range X {
if X[index][0]%2 == 0 && index < len(X)-1 {
continue
}
X[keep] = X[index]
keep++
}
X = X[:keep]
第一:你为什么要这样删除?您是否正在尝试解决更大的问题?
如果这是您想要的方式,那么:
您正在使用缓冲通道,因此删除 goroutine 可能正在从切片中删除项目,而另一个 goroutine 正在处理它,从而导致意外结果。此外,您没有关闭通道,因此 for 循环永远不会终止。
使用无缓冲通道,运行 在单独的 goroutine 中删除循环。然后在wg.Wait
之后关闭通道,终止删除goroutine。
我有一个数组 X,我正在尝试对它进行范围调整并在条件为真时删除一些元素。 在没有任何并发的情况下执行此操作很好,但是当我尝试同时执行此操作时,出现错误: “切片边界超出范围”
func main() {
X := make([][]int32, 10)
for i := 0; i < 10; i++ {
X[i] = []int32{int32(i), int32(i)}
}
ch := make(chan int, 20)
var wg sync.WaitGroup
fmt.Println(X)
for i := 0; i < 20; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for index := range X {
// check some condition
if X[index][0]%2 == 0 && index < len(X)-1 {
ch <- index
break
}
}
}()
}
for {
ind, ok := <-ch
if ok {
X = append(X[:ind], X[ind+1:]...)
} else {
fmt.Println("closed chan")
break
}
}
wg.Wait()
fmt.Println(X)
}
https://play.golang.org/p/YeLamAU5_Rt
有没有办法使用索引并通过通道发送它,然后从不同的 goroutine 中删除相应的元素?
将要保留的元素复制到切片的开头。删除 goroutines。
keep := 0
for index := range X {
if X[index][0]%2 == 0 && index < len(X)-1 {
continue
}
X[keep] = X[index]
keep++
}
X = X[:keep]
第一:你为什么要这样删除?您是否正在尝试解决更大的问题?
如果这是您想要的方式,那么:
您正在使用缓冲通道,因此删除 goroutine 可能正在从切片中删除项目,而另一个 goroutine 正在处理它,从而导致意外结果。此外,您没有关闭通道,因此 for 循环永远不会终止。
使用无缓冲通道,运行 在单独的 goroutine 中删除循环。然后在wg.Wait
之后关闭通道,终止删除goroutine。