聊聊gost的GoSafely

coding

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

  • gost

以上是 聊聊gost的GoSafely 的全部内容, 来源链接: utcz.com/z/508761.html

回到顶部