Golang Go语言中使用 errgroup 停止其他 goroutine
Golang Go语言中使用 errgroup 停止其他 goroutine
目前的需求是这样的
func main() {
errg := new(errgroup.Group)
errg.Go(func() error {
return test1()
})
errg.Go(func() error {
return test2()
})
if err := errg.Wait(); err != nil {
log.Error(err)
}
}
func test1() error {
return nil
}
func test2() error {
return errors.New("test2 err")
}
我如何控制 go 中的协程 有一个错误,其他 go 协程就不会执行? 同时大家如何控制超时的那? 希望能给个范例
更多关于Golang Go语言中使用 errgroup 停止其他 goroutine的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
- 其他 goroutine 就『不会执行』,还是『停止执行』,这是两件事,如果是前者,那就是 sequential 设计,如果后者,还得考量你 gorotuine 中的具体业务,部分情况可以简单使用 context ( chan )检测。
2. 超时如果不会自己设计,那就走 context 方式,如果要采用 timer 务必检查是否 drain 掉 C
更多关于Golang Go语言中使用 errgroup 停止其他 goroutine的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我上面的回答已经相当简陋,顶多是个思路指引,但对于有基础的人而言,我相信很好理解,并且也有诸多设计可以 implement
但我看了一下你的 v2 过往问题,感觉你 go 基础得好好学,别一下蹦个高楼。
最好的做法就是别用 errgroup,那个设计实在太基础,我们都是自己重新做一套控制
需要用到 context 包,比如你想要一个 5 秒钟超时还没执行的 goroutine 自动退出,首先初始化一个 ctx
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
再改造下匿名函数
err.Go(func() error {
select {
case <ctx.Done():
return errors.New(“中止了”)
default:
err := test1()
if err != nil {
cancel()
return err
} else {
return nil
}
}
})
errgroup 在 Google 里也算是最佳实践:-) 是当时 go-library team 觉得非常好用才开源出来的
超时控制 context 就足够了。不会玩?
简单来说 for-select + ctx.Done(),这种方式在各种库里面是遍地开花。
多说一句,开发者不能没有侵入性的中止一个协程,都是必须在协程内监听 ctx 来自行中止的。
在Golang中,errgroup
是一个非常有用的包,它简化了在多个goroutine中处理错误和同步的工作。当你需要在一个goroutine中遇到错误时停止其他goroutine,errgroup
提供了一种简洁的方法来实现这一点。
errgroup.Group
结构体提供了一个Go
方法,用于启动新的goroutine,并且所有由这个Group
启动的goroutine都会共享一个公共的错误通道。一旦其中一个goroutine返回了错误,Group
的Wait
方法将立即返回这个错误,并且你可以使用这个机制来停止其他还在运行的goroutine。
这里是一个简单的示例:
package main
import (
"context"
"errors"
"fmt"
"time"
"golang.org/x/sync/errgroup"
)
func main() {
g, ctx := errgroup.WithContext(context.Background())
g.Go(func() error {
// 模拟一个错误
time.Sleep(1 * time.Second)
return errors.New("something went wrong")
})
g.Go(func() error {
// 检查上下文是否已经被取消
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(2 * time.Second):
return nil
}
})
if err := g.Wait(); err != nil {
fmt.Println("Error:", err)
}
}
在这个示例中,一旦第一个goroutine返回错误,第二个goroutine将通过检查ctx.Done()
来感知到这个错误,并相应地停止自己的工作。