聊聊gost的GoSafely

梦想的初衷 提交于 2021-02-17 11:41:33

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!