gpt4 book ai didi

go - 尝试停止创建更多 goroutine 时出现 panic

转载 作者:行者123 更新时间:2023-12-01 22:44:34 26 4
gpt4 key购买 nike

我正在尝试并行化对 API 的调用以加快速度,但我遇到了一个问题,如果我从其中一个 goroutine 调用中收到错误,我需要停止启动 goroutine 来调用 API。由于我关闭了两次 channel (一次在错误处理部分和执行完成时),我得到一个 panic: close of closed channel错误。有没有一种优雅的方法来处理这个问题而不会让程序 panic ?任何帮助,将不胜感激!

以下是伪代码片段。

for i := 0; i < someNumber; i++ {
go func(num int, q chan<- bool) {
value, err := callAnAPI()
if err != nil {
close(q)//exit from the for-loop
}
// process the value here
wg.Done()
}(i, quit)
}
close(quit)

为了模拟我的场景,我编写了以下程序。一旦满足条件(注释掉),有什么方法可以优雅地退出 for 循环?
package main

import (
"fmt"
"sync"
)

func receive(q <-chan bool) {
for {
select {
case <-q:
return
}
}
}

func main() {
quit := make(chan bool)

var result []int
wg := &sync.WaitGroup{}
wg.Add(10)
for i := 0; i < 10; i++ {
go func(num int, q chan<- bool) {
//if num == 5 {
// close(q)
//}
result = append(result, num)

wg.Done()
}(i, quit)
}
close(quit)
receive(quit)

wg.Wait()

fmt.Printf("Result: %v", result)
}

最佳答案

您可以使用context定义 Context 类型的包,它在 API 边界和进程之间携带截止日期、取消信号和其他请求范围的值。

package main

import (
"context"
"fmt"
"sync"
)

func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // cancel when we are finished, even without error

wg := &sync.WaitGroup{}

for i := 0; i < 10; i++ {
wg.Add(1)
go func(num int) {
defer wg.Done()
select {
case <-ctx.Done():
return // Error occured somewhere, terminate
default: // avoid blocking
}

// your code here
// res, err := callAnAPI()
// if err != nil {
// cancel()
// return
//}

if num == 5 {
cancel()
return
}

fmt.Println(num)

}(i)
}

wg.Wait()

fmt.Println(ctx.Err())
}

试穿: Go Playground

你也可以看看这个 answer以获得更详细的解释。

关于go - 尝试停止创建更多 goroutine 时出现 panic ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60068633/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com