You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过通道与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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 03:40:16