欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    Go协程这样用才安全.docx

    • 资源ID:73273970       资源大小:17.65KB        全文页数:5页
    • 资源格式: DOCX        下载积分:14.8金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要14.8金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    Go协程这样用才安全.docx

    Go协程这样用才安全Go协程有一个不小的问题你无法在父协程中捕获子协程的panic。比方下面的例子: func main() / 祈望捕获所有所有 panic defer func() r := recover() fmt.Println(r) () / 启动新协程 go func() panic(123) () / 等待一下,不然协程可能来不及执行 time.Sleep(1 * time.Second) fmt.Println( 这条消息打印不出来 )自己执行一下就会发现,最后的fmt.Println没有执行,也就是讲开场的recover()没有捕获协程中的panic,整个进程都退出了。 一般的Go框架都是针对每一个恳求启一个新协程,并统一捕获所有的panic。 假如程序员在写业务代码的时候开了新协程而且忘记了在协程中捕获panic的话,效劳的进程就会因为某个未捕获的panic而退出。所以,我在一文中建议*少用或不用协程*。 少用或者不用协程对于大多数业务场景是没有问题。但有些少数场景还是要用协程的。 比方讲我司有一个批量查询接口,一次最多支持查50条信息。但我们的业务要求一次要查100到1000条信息不等。假如不使用协程,需要依次执行2到10次查询,可能就超时了。 不用协程会超时,用协程可能会panic,怎么办呢?最好的方法就是引入框架方法,把Go的协程包装一下。 我们首先定义一个构造体 / Panic 子协程 panic 会被重新包装,添加调用栈信息type Panic struct R interface / recover() 返回值 Stack byte / 当时的调用栈func (p Panic) String() string return fmt.Sprintf( %vn%s , p.R, p.Stack)type PanicGroup struct panics chan Panic / 协程 panic 通知信道 dones chan int / 协程完成通知信道 jobN int32 / 协程并发数量因为Go的channel无法直接初始化,所以需要定义一个工厂方法 func NewPanicGroup() *PanicGroup return PanicGroup panics: make(chan Panic, 8), dones: make(chan int, 8), 针对PanicGroup我们定义Go以及Wait两个方法。 Go方法用来启动新的协程,定义如下: func (g *PanicGroup) Go(f func() *PanicGroup atomic.AddInt32( g.jobN, 1) go func() defer func() if r := recover(); r != nil g.panics - PanicR: r, Stack: debug.Stack() return g.dones - 1 () f() () return g / 方便链式调用这里的核心思想就是启动一个带有recover()的协程,捕获f()执行经过产生的panic并写到g.dones。每个协程启动的时候将计数器加一,方便Wait方法等待。 Wait方法用来等待所有协程完毕或panic,定义如下 func (g *PanicGroup) Wait(ctx context.Context) error for select case -g.dones: if atomic.AddInt32( g.jobN, -1) = 0 return nil case p := -g.panics: panic(p) case -ctx.Done(): return ctx.Err() 假如所有协程都完毕,g.jobN就会等于零,Wait就会返回。假如有协程发生panic,Wait就会通过p := -g.panics捕获并重新拋出。这个时候,框架就能处理这个panic了。 使用起来也是非常的方便 g := NewPanicGroup()g.Go(f1)g.Go(f2)g.Wait(ctx)/ 可以以链式调用err := NewPanicGroup().Go(f1).Go(f2).Wait(ctx)PanicGroup的本质就是各个子协程各自捕获自己的panic,并通过channel传给父协程传递的时候带上调用栈信息。父协程拿到panic信息后重新panic,看起来就像是在父协程拋出来一样。如此就绕过了Go不能在父协程捕获子协程panic的问题,也就防止了局部业务逻辑panic导致整个效劳进程退出的问题。 另外一个需要主意的设计就是Go方法的入参。有人喜欢设计成func(context.Context) error,我想了一下,觉得这种设计不好。 f是由PanicGroup执行的,假如需要传入一个ctx,那势必需要在PanicGroup中保存当前ctx,就是不被推荐的。当然,有人会讲你可以在调Go方法的时候先把f存下来,等到调Wait方法的时候再统一起协程。这样做确实可以不用保存ctx了,却要保存所有的f,我也是不推荐这种做法。 f返回了一个error,这看起来是通用设计,返回报错总是天经地义的。可是,f是由PanicGroup 执行的,假如要返回错误,PanicGroup就需要跟踪哪些协程有报错、哪些没有报错,不同的报错怎样跟协程对应。这会让PanicGroup的设计变得非常复杂。 基于以上两点,我建议将f设计成func(),完全没有参数,PanicGroup只跟踪panic就好了,简单明了。那怎样给协程传参并处理返回结果呢?使用闭包! 这是一个实际的传参例如: func MCount(ctx context.Context, ids int64) (total mapint64int32) m := sync.Mutex g := xsync.NewPanicGroup() chunkSize := 50 for i := 0; i len(ids); i += chunkSize begin := i end := i + chunkSize if end len(ids) end = len(ids) g.Go(func() ts, err := mCount(ctx, idsbegin:end) if err != nil / log error return m.Lock() defer m.Unlock() for k, v := range ts totalk = v ) err = g.Wait(ctx) return

    注意事项

    本文(Go协程这样用才安全.docx)为本站会员(安***)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开