首页>>后端>>Golang->Go语言在for循环中使用协程的注意点

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

时间:2023-11-30 本站 点击:0

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

wg:=sync.WaitGroup{}wg.Add(length)fors:=rangegroup.rtcSubSessionSet{//s.WriteRtcPacket(pkt)gofunc(){deferwg.Done()s.WriteRtcPacket(pkt)}()}wg.Wait()

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

wg:=sync.WaitGroup{}wg.Add(length)fors:=rangegroup.rtcSubSessionSet{//s.WriteRtcPacket(pkt)gofunc(sender*rtc.SubSession){deferwg.Done()sender.WriteRtcPacket(pkt)}(s)}wg.Wait()

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

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

wg:=sync.WaitGroup{}wg.Add(length)fors:=rangegroup.rtcSubSessionSet{//s.WriteRtcPacket(pkt)gofunc(sender*rtc.SubSession){deferfunc(){iferr:=recover();err!=nil{log.Error(fmt.Sprintf("panic%s\n",err))log.Error(fmt.Sprintf(string(debug.Stack())))}}()deferwg.Done()sender.WriteRtcPacket(pkt)}(s)}wg.Wait()

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

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

1.保证捕获协程中的 panic 异常;

2.在协程中使用外部的变量时,应该以传参的方式传递到协程中。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Golang/4587.html