2 回答
TA贡献1790条经验 获得超9个赞
首先,注册一个延迟函数来恢复应该是函数中的第一行,因为因为你是最后做的,它甚至不会被到达,因为defer已经发生恐慌之前的行/代码所以延迟函数没有被注册哪个将恢复恐慌状态。
因此,将您的do()功能更改为:
func do() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Restored:", err)
}
}()
str := "abc"
fmt.Print(str[3])
}
第二:仅此一项不会使您的代码工作,因为您调用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.")
}
输出(在Go Playground上试试):
Restored: runtime error: index out of range
This line should be printed after all those invocations fail.
这当然需要将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.")
}
输出是一样的。在Go Playground上试试这个变体。
TA贡献1846条经验 获得超7个赞
出色地解释了如何正确使用WaitGroup及其功能Wait和Done
我喜欢WaitGroup简单。但是,我不喜欢我们需要传递对 goroutine 的引用,因为这意味着并发逻辑将与您的业务逻辑混合。
所以我想出了这个通用函数来为我解决这个问题:
// Parallelize parallelizes the function calls
func Parallelize(functions ...func()) {
var waitGroup sync.WaitGroup
waitGroup.Add(len(functions))
defer waitGroup.Wait()
for _, function := range functions {
go func(copy func()) {
defer waitGroup.Done()
copy()
}(function)
}
}
所以你的例子可以这样解决:
func do() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
str := "abc"
fmt.Print(str[3])
}
func main() {
Parallelize(do, do, do)
fmt.Println("This line should be printed after all those invocations fail.")
}
如果你想使用它,你可以在这里找到它https://github.com/shomali11/util
- 2 回答
- 0 关注
- 146 浏览
添加回答
举报