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

Go语言切片传参结果不符预期:为何输出{0x03,0x02}?

为什么Go切片传递后输出是{0x03, 0x02}?

要搞懂这个问题,得先理清Go里切片的本质和函数参数传递的规则——Go里所有参数传递都是值传递,切片也不例外,但切片本身是一个包含三个核心字段的结构体,这是问题的关键所在。

先拆解切片的内部结构

每个切片在Go内部都对应这样一个隐形的结构体:

type slice struct {
    ptr *[]byte  // 指向底层数组的指针
    len int      // 当前切片的可用长度
    cap int      // 底层数组的总容量
}

当你把切片作为参数传给函数时,传递的是这个结构体的完整副本,而非底层数组本身。

一步步分析你的代码执行流程

  1. main函数初始化切片a:

    a := []byte{0x01, 0x02}
    

    此时a的结构体状态是:ptr指向底层数组[0x01, 0x02],len=2,cap=2。

  2. 调用test1(a),传递切片副本:
    函数参数t拿到的是a的切片结构体副本,所以t.ptr和a.ptr指向同一个底层数组,t.len和t.cap也都是2。

  3. 执行t[0] = 0x03:
    因为t.ptr和a.ptr指向同一个底层数组,修改t[0]本质是直接修改底层数组的第一个元素,所以a的底层数组会同步变成[0x03, 0x02]。

  4. 执行t = append(t, 0x01):
    此时t.len=2,t.cap=2,append需要添加一个元素,但容量已经耗尽。Go会自动分配一个新的底层数组(通常是原容量的2倍,这里就是4),把原底层数组的元素[0x03, 0x02]拷贝过去,再添加新元素0x01,新的底层数组变成[0x03, 0x02, 0x01, 0x00](末尾的0是默认填充值)。
    这时候,t的结构体被更新:ptr指向这个新的底层数组,len=3,cap=4。但这一切都和a无关——a的结构体还是原来的状态,ptr依然指向旧的底层数组,len和cap还是2。

最终结果

main函数里的a,它的底层数组是[0x03, 0x02],长度是2,所以输出就是{0x03, 0x02}。

补充:如果想让append的结果被main看到怎么办?

有两种常用方式:

  • 让test1函数返回修改后的切片,main里重新赋值给a:
    func test1(t []byte) []byte {
        t[0] = 0x03
        t = append(t, 0x01 )
        return t
    }
    // main里
    a = test1(a)
    
  • 传递切片的指针给函数:
    func test1(t *[]byte) {
        (*t)[0] = 0x03
        *t = append(*t, 0x01 )
    }
    // main里
    test1(&a)
    

内容的提问来源于stack exchange,提问作者P.An

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:59:48