聊聊gost的GoSafely

本文主要研究一下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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值