如何优雅地处理waitgroup中的压缩?
换句话说,在下面的代码片段中,如何捕获gorourines调用方法的恐慌/粉碎do()
?
func do(){
str := "abc"
fmt.Print(str[3])
defer func() {
if err := recover(); err != nil {
fmt.Print(err)
}
}()
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 1; i++ {
wg.Add(1)
go do()
defer func() {
wg.Done()
if err := recover(); err != nil {
fmt.Print(err)
}
}()
}
wg.Wait()
fmt.Println("This line should be printed after all those invocations fail.")
}
Run Code Online (Sandbox Code Playgroud)
首先,注册一个要恢复的延迟函数应该是函数中的第一行,因为你最后这样做,它甚至不会被到达,因为之前的行/代码已经发生了defer
恐慌,所以延迟函数没有被注册会恢复恐慌状态。
因此,将您的do()
功能更改为:
func do() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Restored:", err)
}
}()
str := "abc"
fmt.Print(str[3])
}
Run Code Online (Sandbox Code Playgroud)
其次:仅此一项不会使您的代码正常工作,因为您调用了wg.Defer()
一个延迟函数,该函数只会运行一次main()
完成 - 这永远不会因为您wg.Wait()
在main()
. 因此wg.Wait()
等待调用wg.Done()
,但wg.Done()
调用在返回之前不会运行wg.Wait()
。这是一个僵局。
您应该在延迟函数中wg.Done()
从函数中调用do()
,如下所示:
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.")
}
Run Code Online (Sandbox Code Playgroud)
输出(在Go Playground上尝试):
Restored: runtime error: index out of range
This line should be printed after all those invocations fail.
Run Code Online (Sandbox Code Playgroud)
这当然需要将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.")
}
Run Code Online (Sandbox Code Playgroud)
输出是一样的。在Go Playground上尝试这个变体。
归档时间: |
|
查看次数: |
207 次 |
最近记录: |