php Xiaobian Yuzai reveals a question about slicing for you: Why does the slice written through the channel and goroutine end up being empty? In Go, channels and goroutines are important tools for concurrent programming, but in some cases, using them to write slices can have unexpected results. This article will explain the cause of this problem in detail and provide solutions to help you better understand and deal with this situation.
I run this function:
func run() () { // this slice is going to be filled out by a channel and goroutine. vertices := make([]vertex, 0) var wg sync.waitgroup // obtain a writer to fill out the vertices. writer := writer(&wg, vertices) // run an arbitrary logic to send data to writer. logic(writer) // stop the writer reading on the channel. close(writer) // wait for the write to complete. wg.wait() // see if vertices slice is actually filled out. doublecheckvertices(vertices) }
But in the end, my vertices
slice is empty:
func doublecheckvertices(vertices []vertex) () { // here i notice that `vertices` slice is actually empty :( }
The function that returns writer
is like this:
func writer(wg *sync.waitgroup, vertices []vertex) (chan<- []*triangle3) { // external code writes to this channel. // this goroutine reads the channel and writes to vertices. writer := make(chan []*triangle3) // write by a goroutine. wg.add(1) go func() { defer wg.done() a := vertex{} // read from the channel and write them to vertices. for ts := range writer { for _, t := range ts { a.x = float32(t.v[0].x) a.y = float32(t.v[0].y) a.z = float32(t.v[0].z) vertices = append(vertices, a) } } }() return writer }
Can anyone help me figure out why my vertices
slice ends up empty?
The log shows that the vertices
slice is actually populated. But for some reason it is empty when passed to doublecheckvertices
.
vertices = append(vertices, a) // This Log shows the slice is actually filled out: fmt.Printf("vertices len() is %v\n", len(vertices))
This looks similar to "Pass the slice as a function parameter and modify the original slice"
If you want the goroutine to modify a slice you created externally, you need a pointer to the slice:
func Writer(wg *sync.WaitGroup, vertices *[]Vertex) (chan<- []*Triangle3) { // External code writes to this channel. // This goroutine reads the channel and writes to vertices. writer := make(chan []*Triangle3) // Write by a goroutine. wg.Add(1) go func() { defer wg.Done() a := Vertex{} // Read from the channel and write them to vertices. for ts := range writer { for _, t := range ts { a.X = float32(t.V[0].X) a.Y = float32(t.V[0].Y) a.Z = float32(t.V[0].Z) *vertices = append(*vertices, a) <===== } } }() return writer }
The above is the detailed content of Writing to slices via channels and goroutines: why slices end up empty. For more information, please follow other related articles on the PHP Chinese website!