白首方悔读书迟 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日

悬赏问题

  • ¥20 关于php录入完成后,批量更新数据库
  • ¥15 请教往复密封润滑问题
  • ¥15 cocos creator发布ios包
  • ¥15 comsol压电材料数据
  • ¥35 用python实现除法算法中goldschmidt算法
  • ¥15 汇编代码转换成C代码
  • ¥15 除法算法中的归一化具体是怎么变的?
  • ¥20 集成电路的逻辑电路和晶体管简化图
  • ¥15 下载windows builder后的问题
  • ¥15 端口连接数为什么会有限制