Останов внутри горутины в Go
Останов внутри горутины не ловится перехватом
в другой ветке. recover действует
только в той же горутине, где сработала
паника и где стоит отложенная функция с
перехватом.
Если ветка упала без своего перехвата,
процесс завершается так же, как при
неперехваченном останове в main.
Отложенный recover в главной функции
не увидит панику из фоновой работы.
Запустим ветку с остановом при перехвате
только в main:
package main
import (
"fmt"
"sync"
)
func boom() {
panic("in worker")
}
func main() {
defer func() {
if recover() != nil {
fmt.Println("main caught")
}
}()
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
boom()
}()
wg.Wait()
fmt.Println("after")
}
Строка "main caught" не появляется:
паника пришла из другой ветки. "after"
тоже не успевает: процесс падает вместе
с фоновой функцией.
Перехват нужно ставить внутри той же ветки:
package main
import (
"fmt"
"sync"
)
func risky() {
panic("fail")
}
func main() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
defer func() {
if recover() != nil {
fmt.Println("local ok")
}
}()
risky()
}()
wg.Wait()
fmt.Println("main ok")
}
Дан следующий код:
package main
import "sync"
func bad() {
panic("x")
}
func main() {
defer recover()
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
bad()
}()
wg.Wait()
}
Скажите, завершится ли main штатно
после Wait.
Дана функция:
func alone() {
panic("stop")
}
Запустите alone отдельной веткой
без перехвата внутри нее и скажите, что
случится с процессом.
Скажите, где в втором примере урока должен
стоять recover, чтобы напечатать
"main ok".