zunächst eine latente Funktion Registrierung die erste Zeile in der Funktion zu erholen sollte, da, da Sie es zuletzt tun, ist es nicht einmal, weil die Leitung/Code erreicht wird, bevor die defer
schon Panik und so Die Deferred-Funktion wird nicht registriert, wodurch der Panicing-Status wiederhergestellt würde.
So Ihre do()
Funktion dies ändern:
func do() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Restored:", err)
}
}()
str := "abc"
fmt.Print(str[3])
}
Zweitens: dies allein wird nicht der Code funktioniert, wie Sie wg.Defer()
in einer latenten Funktion aufrufen, die nur main()
Oberflächen einmal laufen würde - was nie da ist Sie rufen wg.Wait()
in Ihrem main()
. So wg.Wait()
wartet auf die wg.Done()
Anrufe, aber wg.Done()
Anrufe werden nicht ausgeführt, bis wg.Wait()
zurückkehrt. Es ist eine Sackgasse.
Sie wg.Done()
aus der do()
Funktion aufrufen sollte, in der latenten Funktion, etwa wie folgt:
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.")
}
Output (versuchen Sie es auf dem Go Playground):
Restored: runtime error: index out of range
This line should be printed after all those invocations fail.
Dies ist natürlich notwendig, um Verschieben Sie die Variable wg
in den globalen Bereich. Eine andere Möglichkeit wäre, sie als Argument an do()
zu übergeben. Wenn Sie sich für diesen Weg entscheiden, beachten Sie, dass Sie einen Zeiger an WaitGroup
übergeben müssen, sonst wird nur eine Kopie übergeben (WaitGroup
ist ein struct
Typ) und der Aufruf WaitGroup.Done()
auf einer Kopie wird keine Auswirkungen auf das Original haben.
Mit vorbei 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.")
}
Ausgabe ist das gleiche. Versuchen Sie diese Variante auf der Go Playground.