這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Go 的標準實現裡 goroutine 是無主的。concurrent.UnboundedExecutor 的目標就是把 ownership 的概念加到 goroutine 上。通過把啟動的goroutine都掛在一個executor上,從而可以跟蹤這一組goroutine的存活狀況。當需要退出的時候,可以把這些個goroutine通過context cancel的方式退出。
package concurrentimport ("context""fmt""time")func ExampleUnboundedExecutor_Go() {executor := NewUnboundedExecutor()executor.Go(func(ctx context.Context) {fmt.Println("abc")})time.Sleep(time.Second)// output: abc}func ExampleUnboundedExecutor_StopAndWaitForever() {executor := NewUnboundedExecutor()executor.Go(func(ctx context.Context) {everyMillisecond := time.NewTicker(time.Millisecond)for {select {case <-ctx.Done():fmt.Println("goroutine exited")returncase <-everyMillisecond.C:// do something}}})time.Sleep(time.Second)executor.StopAndWaitForever()fmt.Println("exectuor stopped")// output:// goroutine exited// exectuor stopped}
在stop的等待過程中,還可以列印日誌輸出哪裡 goroutine 還沒有 quit。這個需要實現 LogInfo 這個 callback。
除了提供goroutine所有權之外。還預設對panic做了recover。對於新啟動的 goroutine 非常容易忘記實現 defer 來 recover 它的 panic。絕大部分時候 goroutine panic 行為應該是 log 下來,而不是直接掛掉整個進程。目前的實現是會調用全域的 HandlePanic 的 callback。
實現代碼:
modern-go/concurrent