通过通道与goroutine向切片写入数据:为何切片最终为空?
问题原因与修复方案
核心原因
Go语言中切片是值类型,当你将vertices传递给Writer函数时,函数内部接收到的是原切片的副本。虽然切片的底层数组是引用类型,但当append操作触发切片扩容(比如原切片容量为0时,第一次append会分配新的底层数组),函数内的副本切片会指向新分配的数组,而Run函数中的原切片仍然指向最初的空数组,因此最终看不到填充后的数据。
你在goroutine内看到的vertices是函数内的副本,它确实被填充了,但这个修改不会同步到原切片上。
修复方案
将切片的指针传递给Writer函数,这样goroutine内的修改会直接作用于原切片:
修改后的Writer函数
func Writer(wg *sync.WaitGroup, vertices *[]Vertex) chan<- []*Triangle3 { writer := make(chan []*Triangle3) wg.Add(1) go func() { defer wg.Done() a := Vertex{} 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 }
修改后的Run函数调用
func Run() { vertices := make([]Vertex, 0) var wg sync.WaitGroup // 传入切片的指针 writer := Writer(&wg, &vertices) Logic(writer) close(writer) wg.Wait() DoublecheckVertices(vertices) }
这样修改后,goroutine内的append操作会直接修改原切片的底层数组(或扩容后的新数组),Run函数中的vertices就能正确获取到填充后的数据。
内容的提问来源于stack exchange,提问作者Megidd
相关产品推荐
相关产品推荐

