从切片中同时删除

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]

Run it on the playground.

第一:你为什么要这样删除?您是否正在尝试解决更大的问题?

如果这是您想要的方式,那么:

您正在使用缓冲通道,因此删除 goroutine 可能正在从切片中删除项目,而另一个 goroutine 正在处理它,从而导致意外结果。此外,您没有关闭通道,因此 for 循环永远不会终止。

使用无缓冲通道,运行 在单独的 goroutine 中删除循环。然后在wg.Wait之后关闭通道,终止删除goroutine。