3 回答
TA贡献1936条经验 获得超6个赞
无论如何都会panic
终止进程,因为没有人从中恢复。如果你想在一个 goroutine 中从 panic 中恢复,你必须将recover
调用堆栈包装在同一个 goroutine 中。
wg.Done
在这种情况下,将由defer
声明调用。但是这个过程可能会在主 goroutine 完成之前结束wg.Wait
。
TA贡献1869条经验 获得超4个赞
参考src/builtin/builtin.go
panic 内置函数停止当前 goroutine 的正常执行。当函数 F 调用 panic 时,F 的正常执行会立即停止。任何被 F 延迟执行的函数都以通常的方式运行,然后 F 返回给它的调用者。对于调用者 G,调用 F 就像调用 panic,终止 G 的执行并运行任何延迟函数。这一直持续到执行 goroutine 中的所有函数都以相反的顺序停止。此时,程序终止并报告错误情况,包括 panic 的参数值。这种终止序列称为 panicing,可以通过内置函数 recover 来控制。
之后panic
,defer
将调用 func。
在操场上检查一下:https ://play.golang.org/p/yrXkEbE1Af7
package main
import (
"sync"
"fmt"
)
func main() {
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
defer func(){
fmt.Println("expected to be called after panic")
wg.Done()
}()
// Long running task
panic("Something unexpected happened.")
}()
wg.Wait()
}
输出
expected to be called after panic
panic: Something unexpected happened.
goroutine 5 [running]:
main.main.func1(0x416020, 0x0)
/tmp/sandbox946785562/main.go:17 +0x60
created by main.main
/tmp/sandbox946785562/main.go:11 +0x80
那么你的第二个问题,“如何防止这种情况发生?”
如前所述,您可以recover在panic
游乐场:https://play.golang.org/p/76pPrCVYN8u
package main
import (
"sync"
"fmt"
)
func main() {
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
defer func(){
if x:=recover();x!=nil{
fmt.Printf("%+v\n",x)
}
wg.Done()
}()
// Long running task
panic("Something unexpected happened.")
}()
wg.Wait()
for i:=0;i<10;i++{
fmt.Println(i)
}
}
输出
Something unexpected happened.
0
1
2
3
4
5
6
7
8
9
TA贡献1829条经验 获得超7个赞
可以通过添加来引发不需要的行为defer time.Sleep(time.Second):
func main() {
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
defer time.Sleep(time.Second)
defer wg.Done()
// Long running task
panic("Something unexpected happened.")
}()
wg.Wait()
}
D:\Projects\Code\Go\src\zyl\testexit>go build .
D:\Projects\Code\Go\src\zyl\testexit>.\testexit.exe
D:\Projects\Code\Go\src\zyl\testexit>echo %errorlevel%
0
该问题的解决方案是不延迟调用Done()并将其放在最后:
func main() {
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
// Long running task which might panic
wg.Done()
}()
wg.Wait()
}
在上面的代码中,不存在对 go routine 行为的实现细节的依赖,并且在发生 panic 时总是会失败。
- 3 回答
- 0 关注
- 129 浏览
添加回答
举报