英文:
Writing to a slice by a channel and a goroutine: why slice is eventually empty
问题
我运行了这个函数:
func Run() () {
// 这个切片将通过通道和 goroutine 填充。
vertices := make([]Vertex, 0)
var wg sync.WaitGroup
// 获取一个写入器来填充顶点。
writer := Writer(&wg, vertices)
// 运行一个任意的逻辑来向写入器发送数据。
Logic(writer)
// 停止写入器在通道上的读取。
close(writer)
// 等待写入完成。
wg.Wait()
// 检查顶点切片是否实际上已经填充。
DoublecheckVertices(vertices)
}
但最终,我的 vertices
切片是空的:
func DoublecheckVertices(vertices []Vertex) () {
// 在这里我注意到 `vertices` 切片实际上是空的 :(
}
返回 writer
的函数大致如下:
func Writer(wg *sync.WaitGroup, vertices []Vertex) (chan<- []*Triangle3) {
// 外部代码向该通道写入。
// 这个 goroutine 读取通道并写入 vertices。
writer := make(chan []*Triangle3)
// 通过 goroutine 进行写入。
wg.Add(1)
go func() {
defer wg.Done()
a := Vertex{}
// 从通道读取并将其写入 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
函数时它是空的。
vertices = append(vertices, a)
// 这个日志显示切片实际上已经填充:
fmt.Printf("vertices len() is %v\n", len(vertices))
英文:
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 eventually, my vertices
slice is empty:
func DoublecheckVertices(vertices []Vertex) () {
// Here I notice that `vertices` slice is actually empty :(
}
The function which returns the writer
is something 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 anybody help me with figuring out why my vertices
slice is eventually empty?
Logs
Logs indicate that the vertices
slice is actually filled out. But for some reason, it's empty when it's 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))
答案1
得分: 1
这似乎与"将切片作为函数参数传递,并修改原始切片"类似。
如果你希望你的goroutine修改在外部创建的切片,你需要一个指向该切片的指针:
func Writer(wg *sync.WaitGroup, vertices *[]Vertex) (chan<- []*Triangle3) {
// 外部代码向该通道写入数据。
// 这个goroutine读取通道并将数据写入vertices。
writer := make(chan []*Triangle3)
// 由一个goroutine进行写入。
wg.Add(1)
go func() {
defer wg.Done()
a := Vertex{}
// 从通道读取数据并将其写入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
}
英文:
That seems similar to "Pass slice as function argument, and modify the original slice"
If you want your goroutine to modify the slice you created outside, you would need a pointer to that 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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论