Search code examples
goconcurrencygoroutine

Deleting concurrently from a slice


I've got an array X and I'm trying to range over it and delete some elements if a condition is true. Doing this without any concurrency works fine, but when I try to do this concurrently I get the error: "slice bounds out of range"

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

Is there any way to use the indexes and send it over a channel then delete the corresponding elements from different goroutines?


Solution

  • First: why are you trying to delete like this? Is there a larger problem you are trying to solve?

    If this is how you want to do it, then:

    You are using a buffered channel, so the deleting goroutine can be deleting items from the slice while the other goroutine is working on it, causing unexpected results. Also, you are not closing the channel, so the for-loop never terminates.

    Use an unbuffered channel, and run the deletion loop in a separate goroutine. Then close the channel after wg.Wait to terminate the deleting goroutine.