白首方悔读书迟 2022-03-10 20:17 采纳率: 100%
浏览 96
已结题

go 多重循环中对结构体切片append 最后结果和预期不一致

问题遇到的现象和发生背景

go 多重循环中对结构体切片append 最后结果和预期不一致

问题相关代码,请勿粘贴截图
package main

import (
    "fmt"
    _ "github.com/mattn/go-oci8"
    "strconv"
    _ "test-app/internal/packed"
)

type A struct {
    aa int
    ab string
    cc []B
}
type B struct {
    ba int
    bb string
}
func main() {
    var q1 []A

    q2:=make([]A,0)
    q1=[]A{{aa:1,ab:"1",cc:[]B{{ba: 1},{ba: 2},{ba: 3}}},{aa:2,ab:"2",cc:[]B{{ba: 1},{ba: 2},{ba: 3}}}}
    number:=0
    for _, q1v := range q1 {
        x:=[]string{"11","22"}
        for _, iv2 := range x {
            ls:=q1v
            for i, _ := range ls.cc {
                number+=1
                sj:=iv2 +"----"+strconv.Itoa(number)
                ls.cc[i].bb=sj
            }
            fmt.Printf("加入临时值:%+v\n",ls)
            q2=append(q2,ls)
        }

    }
    for _, a := range q2 {
        fmt.Printf("输出:%+v\n",a)
    }
    //fmt.Printf("s%+v",q2)
}

运行结果及报错内容

img

可以看出最后输出的和加入临时值的时候并不一样

我的解答思路和尝试过的方法

没找到解决方案

我想要达到的结果

最后输出的结果和 加入临时值一致

  • 写回答

4条回答 默认 最新

  • ProblemTerminator Go领域优质创作者 2022-03-10 22:26
    关注

    哈喽,我来告诉你原具体情况,
    1,append到q2中的每次的数据和最后打出来的q2确实是不一样的,你没看错
    2,最外层循环是两次,每隔两次q2的值会被改一下,改的新值就是最内层循环ls.cc[i].bb = sj的值,i的值每次分别为0,1,2也就是取的i=2时候的值
    3,每次执行到最后一次ls.cc[i].bb = sj的时候,看起来是改的ls,实际上连位置为i的q2的值也一块改了;并且q1v和q2是同步修改的,改ls时q1v跟着改;
    4,实际上最终q2里的值都是q1v的每次最新值,那么到这里原因就浮现了,第二层循环每进行一次都把最新的q1v赋给了ls变量,换句话说,代码里的ls实际上意义不大,有和没有效果一样(q2直接拼接q1v的值也是这个结果)
    ===>q2每次拼接的对象地址和ls在最内层循环最后一次修改的值都在同一个地址,因此q2跟着改了

    最后,可以把number := 0 调整到第二和第三层循环之间就看得比较清楚了
    如果想要每次加的值和最终q2元素相同,可以这么改:
    func main() {
    q2 := make([]A, 0)
    q1 := []A{
    {aa: 1, ab: "1", cc: []B{{ba: 1}, {ba: 2}, {ba: 3}}},
    {aa: 2, ab: "2", cc: []B{{ba: 1}, {ba: 2}, {ba: 3}}},
    }
    for _, q1v := range q1 { // 2次
    for _, iv2 := range []string{"11", "22"} { // 2次
    ls,number := &A{aa: q1v.aa, ab: q1v.ab, cc: make([]B, 3)},0
    for i := range q1v.cc { // 3次
    number += 1
    sj := iv2 + "----" + strconv.Itoa(number)
    ls.cc[i].ba = q1v.cc[i].ba
    ls.cc[i].bb = sj
    }
    fmt.Printf("加入临时值:%+v\n", ls)
    q2 = append(q2, *ls)
    }
    }
    for _, a := range q2 {
    fmt.Printf("输出:%+v\n", &a)
    }
    //fmt.Printf("s%+v",q2)
    }

    如果解决了疑问,欢迎采纳哦!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 3月19日
  • 已采纳回答 3月11日
  • 赞助了问题酬金50元 3月10日
  • 创建了问题 3月10日

悬赏问题

  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)
  • ¥15 Windows11, backspace, enter, space键失灵