从 goroutine 通道读取而不阻塞

我有两个 goroutines:mainworker和 a helper,它为了一些帮助而分拆出来。 helper可能会遇到错误,所以我使用通道将错误helper从worker.


func helper(c chan <- error) (){

    //do some work

    c <- err // send errors/nil on c

}

这是如何helper()调用的:


func worker() error {

    //do some work

    c := make(chan error, 1)

    go helper(c)

    err := <- c

    return err

}

问题:


语句是否err := <- c阻塞worker?我不这么认为,因为通道是缓冲的。


如果它是阻塞的,我如何使它成为非阻塞的?我的要求是worker让其调用者继续进行其余的工作,而无需等待值出现在通道上。


谢谢。


ABOUTYOU
浏览 133回答 3
3回答

MMTTMM

您可以轻松验证func helper(c chan<- error) {&nbsp; &nbsp; time.Sleep(5 * time.Second)&nbsp; &nbsp; c <- errors.New("") // send errors/nil on c}func worker() error {&nbsp; &nbsp; fmt.Println("do one")&nbsp; &nbsp; c := make(chan error, 1)&nbsp; &nbsp; go helper(c)&nbsp; &nbsp; err := <-c&nbsp; &nbsp; fmt.Println("do two")&nbsp; &nbsp; return err}func main() {&nbsp; &nbsp; worker()}问:语句 err := <- c 阻塞工作者吗?我不这么认为,因为通道是缓冲的。- 答:&nbsp;err := <- c会阻止工人。问:如果是阻塞的,我如何使它成为非阻塞的?我的要求是让 worker 及其调用者继续完成其余的工作,而无需等待值出现在通道上。A:如果您不想阻止,只需删除err := <-c.&nbsp;如果你在最后需要错误,只需移动err := <-c到最后。没有阻塞就无法读取通道,如果没有阻塞就不能再执行此代码,除非您的代码处于循环中。Loop:&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case <-c:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break Loop&nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //default will go through without blocking&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // do something&nbsp; &nbsp; }你见过errgroup或 waitgroup 吗?它使用原子、取消上下文和sync.Once 来实现这一点。https://github.com/golang/sync/blob/master/errgroup/errgroup.gohttps://github.com/golang/go/blob/master/src/sync/waitgroup.go或者你可以直接使用它,运行你的函数,然后在你想要的任何地方等待错误。

吃鸡游戏

在您的代码中,其余工作与帮助程序是否遇到错误无关。其余工作完成后,您可以简单地从频道接收。func worker() error {&nbsp; &nbsp; //do some work&nbsp; &nbsp; c := make(chan error, 1)&nbsp; &nbsp; go helper(c)&nbsp; &nbsp; //do rest of the work&nbsp; &nbsp; return <-c}

拉丁的传说

我想你需要这个代码..运行此代码package mainimport (&nbsp; &nbsp; "log"&nbsp; &nbsp; "sync")func helper(c chan<- error) {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; var err error = nil&nbsp; &nbsp; &nbsp; &nbsp; // do job&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c <- err // send errors/nil on c&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}func worker(c chan error) error {&nbsp; &nbsp; log.Println("first log")&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; helper(c)&nbsp; &nbsp; }()&nbsp; &nbsp; count := 1&nbsp; &nbsp; Loop:&nbsp; &nbsp; &nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case err := <- c :&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Println(count, " log")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count++&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isFinished := false&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // do your job&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if isFinished {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break Loop // remove this when you test&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; return nil}func main() {&nbsp; &nbsp; wg := sync.WaitGroup{}&nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; c := make(chan error, 1)&nbsp; &nbsp; &nbsp; &nbsp; worker(c)&nbsp; &nbsp; &nbsp; &nbsp; wg.Done()&nbsp; &nbsp; }()&nbsp; &nbsp; wg.Wait()}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go