白首方悔读书迟 2022-04-19 11:35 采纳率: 100%
浏览 58
已结题

go 匿名函数协程中直接修改上级切片的安全性

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

我想确认一下下列代码是否会有问题

问题相关代码,请勿粘贴截图
type bb struct {
    a int
    b string
}
func a1() {
    aa :=[]bb{{a: 0,b: "b0",},{a:1,b:"b1"},{a:2,b:"b2"},{a:3,b:"b3"},{a:4,b:"b4"}}
    for i := 0; i < 5; i++ {
        go func(wz int) {
            aa[wz].b="完毕"+strconv.Itoa(wz)
        }(i)
    }
time.Sleep(time.Millisecond*5000)
    fmt.Printf("最终结果%+v",aa)
}

运行结果及报错内容

最终结果符合预期

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

目前看来结果达到我的预期

我想要达到的结果

因为项目中我不想用chan来通讯所以想用上述带的思路.
我想知道在实际项目中这样用是否会有问题,实际中bb struct结构体比较复杂

  • 写回答

5条回答 默认 最新

  • ohko 2022-04-24 19:23
    关注

    从代码逻辑来看,没毛病,并且结果也是与你的预期一致的:

    1. 由于这里是用的传值匿名函数,go func(wz int)(i),所有没有多协程问题。
    2. 后面的sleep 5秒很关键,但是如果等待的时间不够,上面的协程执行的内容如果比较复杂时,耗时比较多的话,结果可能就会和预期的不同。
    3. 如果aa切片数据比较多时,就会启动非常多的协程。

    最好是将sleep 5秒改进一下,用一个Group锁会好得多。

    func a1() {
        var wg sync.WaitGroup // 添加定义
        aa := []bb{{a: 0, b: "b0"}, {a: 1, b: "b1"}, {a: 2, b: "b2"}, {a: 3, b: "b3"}, {a: 4, b: "b4"}}
    
        wg.Add(len(aa)) // 添加计数
        for i := 0; i < 5; i++ {
            go func(wz int) {
                aa[wz].b = "完毕" + strconv.Itoa(wz)
                wg.Done() // 完成一个计数
            }(i)
        }
    
        wg.Wait() // time.Sleep(time.Millisecond * 5000)
        fmt.Printf("最终结果%+v", aa)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 5月4日
  • 已采纳回答 4月26日
  • 创建了问题 4月19日

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题