php小编鱼仔为您揭示一个关于切片的问题:为什么通过通道和 goroutine 写入切片最终为空?在Go语言中,通道和 goroutine 是并发编程的重要工具,但在某些情况下,使用它们写入切片可能会出现意外结果。本文将详细解释这个问题的原因,并提供解决方案,帮助您更好地理解和处理这种情况。
我运行这个函数:
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) }
但最终,我的 vertices
切片是空的:
func doublecheckvertices(vertices []vertex) () { // here i notice that `vertices` slice is actually empty :( }
返回 writer
的函数是这样的:
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 }
任何人都可以帮我弄清楚为什么我的 vertices
切片最终是空的吗?
日志表明 vertices
切片实际上已填充。但由于某种原因,传递给doublecheckvertices
切片实际上已填充。但由于某种原因,传递给doublecheckvertices
时为空。
vertices = append(vertices, a) // This Log shows the slice is actually filled out: fmt.Printf("vertices len() is %v\n", len(vertices))
这看起来类似于“将切片作为函数参数传递,并修改原始切片”
如果您希望 goroutine 修改您在外部创建的切片,则需要一个指向该切片的指针:
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 }
以上是通过通道和 goroutine 写入切片:为什么切片最终为空的详细内容。更多信息请关注PHP中文网其他相关文章!