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

Go语言append添加第二个元素时首个元素被修改的问题排查

Go JSON解析切片引用问题分析与解决

问题原因

你在循环外部仅声明了一次buf []Human切片,而Go语言中切片是引用类型,它本身只存储底层数组的指针、长度和容量。第一次json.Unmarshal将数据解析到buf的底层数组后,你把buf添加到people切片中,此时people的第一个元素是buf的引用(指向同一个底层数组)。

第二次执行json.Unmarshal时,由于buf的底层数组容量足够容纳新数据,Unmarshal会直接覆盖底层数组里的原有内容,这就导致people中已存在的第一个元素(因为是引用)指向的内容也被修改,最终people里的两个元素都指向同一个底层数组,内容完全一致。

解决方法

有两种常用的解决思路:

方法1:每次循环重新声明buf

将var buf []Human移到循环内部,每次迭代都创建一个新的切片,这样每次解析的结果会存储在独立的底层数组中,避免引用复用:

package main

import (
    "encoding/json"
    "fmt"
)

type Human struct {
    N string `json:"n"`
    C string `json:"c"`
}

func funcname(jDL ...[]byte) {
    jDL_len := len(jDL)
    people := [][]Human{}
    var err error
    for i := 0; i < jDL_len; i++ {
        var buf []Human // 每次循环创建新切片
        err = json.Unmarshal(jDL[i], &buf)
        fmt.Println("buf", i, buf)
        people = append(people, buf)
        fmt.Println("people", i, people)
    }
    jsoned, err := json.Marshal(people)
    fmt.Println("jsoned", string(jsoned))
    fmt.Println("err", err)
}

func main() {
    i0 := []byte(`[
            {
                "n": "Alice",
                "c": "A1"
            },
            {
                "n": "Bob",
                "c": "A2"
            }
        ]`)
    i1 := []byte(`[
            {
                "n": "Clark",
                "c": "B1"
            },
            {
                "n": "Davis",
                "c": "B2"
            }
        ]`)
    funcname(i0, i1)
}

方法2:复制buf内容后再append

如果需要保留循环外的buf声明,可以在append前创建buf的副本,确保添加到people的是独立的切片:

修改循环内的append语句为:

people = append(people, append([]Human(nil), buf...))

验证结果

修改后运行代码,输出会符合预期:

buf 0 [{Alice A1} {Bob A2}]
people 0 [[{Alice A1} {Bob A2}]]
buf 1 [{Clark B1} {Davis B2}]
people 1 [[{Alice A1} {Bob A2}] [{Clark B1} {Davis B2}]]
jsoned [[{"n":"Alice","c":"A1"},{"n":"Bob","c":"A2"}],[{"n":"Clark","c":"B1"},{"n":"Davis","c":"B2"}]]
err <nil>

内容的提问来源于stack exchange,提问作者max

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:42:45