聊聊gost的GoSafely

codecraft · · 485 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

本文主要研究一下gost的GoSafely

GoSafely

gost/runtime/goroutine.go

func GoSafely(wg *sync.WaitGroup, ignoreRecover bool, handler func(), catchFunc func(r interface{})) {
    if wg != nil {
        wg.Add(1)
    }
    go func() {
        defer func() {
            //......
        }()
        handler()
    }()
}
GoSafely接收WaitGroup、ignoreRecover、handler、catchFunc参数,其大致的模板是,首先对WaitGroup进行add(1),然后一步执行带defer的handler

defer

gost/runtime/goroutine.go

        defer func() {
            if r := recover(); r != nil {
                if !ignoreRecover {
                    fmt.Fprintf(os.Stderr, "%s goroutine panic: %v\n%s\n",
                        time.Now(), r, string(debug.Stack()))
                }
                if catchFunc != nil {
                    //......
                }
            }
            if wg != nil {
                wg.Done()
            }
        }()
GoSafely的defer先执行recover(),然后根据ignoreRecover判断是否打印err,最后处理WaitGroup,与普通recover不同的是多了一个catchFunc处理

catchFunc

gost/runtime/goroutine.go

                if catchFunc != nil {
                    if wg != nil {
                        wg.Add(1)
                    }
                    go func() {
                        defer func() {
                            if p := recover(); p != nil {
                                if !ignoreRecover {
                                    fmt.Fprintf(os.Stderr, "recover goroutine panic:%v\n%s\n",
                                        p, string(debug.Stack()))
                                }
                            }

                            if wg != nil {
                                wg.Done()
                            }
                        }()
                        catchFunc(r)
                    }()
                }
catchFunc算是一个mini版的GoSafely,先执行wg.Add(1),再异步执行func,异步func里头先注册defer,处理recover及wg,然后执行catchFunc

实例

gost/runtime/goroutine_test.go

func TestGoSafe(t *testing.T) {
    times := int32(1)

    var wg sync.WaitGroup
    GoSafely(&wg,
        false,
        func() {
            panic("hello")
        },
        func(r interface{}) {
            atomic.AddInt32(&times, 1)
        },
    )

    wg.Wait()
    assert.True(t, atomic.LoadInt32(&times) == 2)

    GoSafely(nil,
        false,
        func() {
            panic("hello")
        },
        func(r interface{}) {
            atomic.AddInt32(&times, 1)
        },
    )
    time.Sleep(1e9)
    assert.True(t, atomic.LoadInt32(&times) == 3)
}
这里模拟了一下handler产生panic,一个有WaitGroup,一个没有WaitGroup的场景

小结

gost提供了GoSafely方法,它接收WaitGroup、ignoreRecover、handler、catchFunc参数,其大致的模板是,首先对WaitGroup进行add(1),然后一步执行带defer的handler。catchFunc算是一个mini版的GoSafely,先执行wg.Add(1),再异步执行func,异步func里头先注册defer,处理recover及wg,然后执行catchFunc。

doc


有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:codecraft

查看原文:聊聊gost的GoSafely

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

485 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传