まず、あなたが最後にそれを行うことから、それも到達できないので、関数の最初の行でなければなりません回復する繰延機能を登録するためのライン/コードdefer
すでにパニックとその前に遅延機能が登録されず、これにより、状態が復元されます。
だからこれにあなたのdo()
機能を変更します。
func do() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Restored:", err)
}
}()
str := "abc"
fmt.Print(str[3])
}
第二:あなたは一度だけmain()
仕上げ実行します繰延機能にwg.Defer()
を呼ぶとして単独でこれは、あなたのコードの仕事をすることはありません - ためになることはありませんmain()
にwg.Wait()
と電話してください。したがってwg.Wait()
はwg.Done()
コールを待ちますが、wg.Done()
コールはwg.Wait()
リターンまで実行されません。それはデッドロックです。あなたは繰延機能で、do()
関数からwg.Done()
を呼び出す必要があり
、このような何か:
var wg sync.WaitGroup
func do() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
wg.Done()
}()
str := "abc"
fmt.Print(str[3])
}
func main() {
for i := 0; i < 1; i++ {
wg.Add(1)
go do()
}
wg.Wait()
fmt.Println("This line should be printed after all those invocations fail.")
}
出力(Go Playground上でそれを試してみてください):
Restored: runtime error: index out of range
This line should be printed after all those invocations fail.
このコースのために必要変数wg
をグローバルスコープに移動します。別のオプションは、引数としてdo()
に渡すことです。このようにする場合は、WaitGroup
へのポインタを渡さなければならないことに注意してください。それ以外の場合は、コピーのみが渡されます(WaitGroup
はstruct
タイプ)、コピーにWaitGroup.Done()
を呼び出しても元のものには影響しません。 WaitGroup
do()
に渡すことで
:
func do(wg *sync.WaitGroup) {
defer func() {
if err := recover(); err != nil {
fmt.Println("Restored:", err)
}
wg.Done()
}()
str := "abc"
fmt.Print(str[3])
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 1; i++ {
wg.Add(1)
go do(&wg)
}
wg.Wait()
fmt.Println("This line should be printed after all those invocations fail.")
}
出力は同じです。この変形はGo Playgroundでお試しください。