Najpierw rejestracji funkcję odroczony do odzyskania powinna być w pierwszej linii w funkcji, jak to zrobić, ponieważ ostatni, nie będzie nawet być osiągnięte, ponieważ linia/code przed defer
już paniki i tak funkcja odroczona nie zostanie zarejestrowana, co przywróci stan panowania.
tak zmienić funkcję do()
do tego:
func do() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Restored:", err)
}
}()
str := "abc"
fmt.Print(str[3])
}
Po drugie: to sam nie zrobi swoją pracę kodu, jak to nazywasz wg.Defer()
w funkcji odroczony które uruchamiane tylko raz main()
wykończeń - który nigdy się tak dlatego, dzwonisz pod numer wg.Wait()
w swoim main()
. Tak więc wg.Wait()
czeka na wywołania wg.Done()
, ale połączenia wg.Done()
nie zostaną uruchomione, dopóki nie zostaną przywrócone po wg.Wait()
. To jest impas.
Należy zadzwonić wg.Done()
z funkcji do()
w funkcji odroczonym coś takiego:
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 (spróbuj go na Go Playground):
Restored: runtime error: index out of range
This line should be printed after all those invocations fail.
To oczywiście potrzebne do przenieś zmienną wg
do zasięgu globalnego. Inną opcją byłoby przekazanie jej jako argumentu do do()
. Jeśli zdecydujesz się pójść tą drogą, pamiętaj, że musisz przekazać wskaźnik do WaitGroup
, w przeciwnym razie zostanie przekazana tylko kopia (WaitGroup
to typ struct
), a wywołanie WaitGroup.Done()
na kopii nie będzie miało wpływu na oryginał.
Przy przejściu WaitGroup
do 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.")
}
wyjściowa jest taka sama. Wypróbuj ten wariant na Go Playground.