EasyDSS开发中Go语言在for循环中使用协程的注意点

之前我们介绍过EasyDSS开发中对野协程的管理,有兴趣的朋友可以了解一下:EasyDSS协程出现panic并导致程序退出,如何对野协程进行管理?在 EasyDSS 的程序开发中,有时为了加快速度,会在 for 循环中采用协程的方式进行代码编写,类似代码如下:

wg := sync.WaitGroup{}
wg.Add(length)
for s := range group.rtcSubSessionSet {
   //s.WriteRtcPacket(pkt)
   go func() {
      defer wg.Done()
      s.WriteRtcPacket(pkt)
   }()
}
wg.Wait()

以上代码 s 为从集合中取出的指针变量,因为采用协程的方式, go func(){} 代码会新启动一个协程进行运行。for 循环进入下一次循环,此时 s 的值被改变,因此会导致发的包会乱序。因此修改代码如下:

wg := sync.WaitGroup{}
wg.Add(length)
for s := range group.rtcSubSessionSet {
   //s.WriteRtcPacket(pkt)
   go func(sender *rtc.SubSession) {
      defer wg.Done()

      sender.WriteRtcPacket(pkt)
   }(s)
}
wg.Wait()

以上代码将前一个指针变量以传递参数的方式传递到协程中,即使下一次循环中 s 改变,也不会出现问题。

以上代码可以正常运行,但是如果协程中出现 panic 错误,就会导致整个程序退出,导致系统不稳定,因此我们进一步优化代码如下:

wg := sync.WaitGroup{}
wg.Add(length)
for s := range group.rtcSubSessionSet {
   //s.WriteRtcPacket(pkt)
   go func(sender *rtc.SubSession) {
      defer func() {
         if err := recover(); err != nil {
            log.Error(fmt.Sprintf("panic %s\n", err))
            log.Error(fmt.Sprintf(string(debug.Stack())))
         }
      }()
      defer wg.Done()

      sender.WriteRtcPacket(pkt)
   }(s)
}
wg.Wait()

在代码的最开始加上 recover() 函数捕获所有的 panic 信息,这样既可以知道哪里出错,也能保证程序稳定运行。

总结以下在写协程的时候主要注意两点:

1.保证捕获协程中的 panic 异常;
2.在协程中使用外部的变量时,应该以传参的方式传递到协程中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值