パニックしないでください:Ergroup Goroutinesでパニックを捕えてください
イメージバイNicosmos , パブリックドメイン, Wikimedia
TLドクターバージョン
StevenACoffman/errgroup ゴーの素晴らしい代わるドロップ
sync/errgroup
しかし、それはエラーにGoroutineパニックを変換します.なぜあなたが欲しい
中
net/http
Galoutineに対応する各リクエストに対してパニックハンドラをインストールします.Goroutinesは、親Goroutinesからパニックハンドラを継承することはできません.
だから
panic()
子供Goroutinesのうちの1人で、プログラム全体を殺します.だから生産では、いつでも使用する
sync.errgroup
, あなたは常にAを追加することを忘れないように規律を持っている繰延する
recover()
すべての新しいGoroutineの先頭に、任意のパニックをエラーに変換します. defer func() {
if rec := recover(); rec != nil {
err = FromPanicValue(rec)
}
}()
これを見ることができますaction in the Go Playground here . また、スタックトレースを失わないように注意してください.The CollectStack
私がここで使用する関数は、簡単に簡略化されているので、スキップしないため、少しノイズが追加されますFromPanicValue
and CollectStack
フレーム.🤷♂️func FromPanicValue(i interface{}) error {
switch value := i.(type) {
case nil:
return nil
case string:
return fmt.Errorf("panic: %v\n%s", value, CollectStack())
case error:
return fmt.Errorf("panic in errgroup goroutine %w\n%s", value, CollectStack())
default:
return fmt.Errorf("unknown panic: %+v\n%s", value, CollectStack())
}
}
func CollectStack() []byte {
buf := make([]byte, 64<<10)
buf = buf[:runtime.Stack(buf, false)]
return buf
}
鉱山労働者の同僚Ben Kraft , アラウンドアラウンドアラウンドラッパーコードsync/errgroup
そのboilerplateを避けるために(そして、必要な規律).彼の許可を得てlightly modified it toより一般的なGOコミュニティのために我々の個人的な仕事倉庫からそれを持ち上げてください.
StevenACoffman/errgroup
ゴーの素晴らしい代わるドロップsync/errgroup
それがエラーにGoroutineパニックを変えるという違いで.あなたはsee it in use in the playground または、
package main
import (
"fmt"
"github.com/StevenACoffman/errgroup"
)
func main() {
g := new(errgroup.Group)
var urls = []string{
"http://www.golang.org/",
"http://www.google.com/",
"http://www.somestupidname.com/",
}
for i := range urls {
// Launch a goroutine to fetch the URL.
i := i // https://golang.org/doc/faq#closures_and_goroutines
g.Go(func() error {
// deliberate index out of bounds triggered
fmt.Println("Fetching:", i, urls[i+1])
return nil
})
}
// Wait for all HTTP fetches to complete.
err := g.Wait()
if err == nil {
fmt.Println("Successfully fetched all URLs.")
} else {
fmt.Println(err)
}
}
対位法
があるan interesting discussion これには別の見方があります.
いくつかの例外では、パニックのプログラムをクラッシュする必要があります.私は開発とテストでそれでOKです、しかし、夜にはむしろ眠ります.
先行技術
ただの検索だけで、私はいくつかの既存のオープンソースの例を見つけました.
Kratosグループ
マイクロサービスのためのKratos Goフレームワークは類似しているerrgroup
解決法
Sergey AlexandrovichによるPanicgroup
記事でErrors in Go:
From denial to acceptance ,
(これはパニックベースのフロー制御を提唱している😱), 彼らは
PanicGroup
これは大体同じです.type PanicGroup struct {
wg sync.WaitGroup
errOnce sync.Once
err error
}
func (g *PanicGroup) Wait() error {
g.wg.Wait()
return g.err
}
func (g *PanicGroup) Go(f func()) {
g.wg.Add(1)
go func() {
defer g.wg.Done()
defer func(){
if r := recover(); r != nil {
if err, ok := r.(error); ok {
// We need only the first error, sync.Once is useful here.
g.errOnce.Do(func() {
g.err = err
})
} else {
panic(r)
}
}
}()
f()
}()
}
私はフィードバックや改善のための提案をいただければ幸いです!Reference
この問題について(パニックしないでください:Ergroup Goroutinesでパニックを捕えてください), 我々は、より多くの情報をここで見つけました https://dev.to/stevenacoffman/don-t-panic-catching-panics-in-errgroup-5hnテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol