新手问题 golang在goroutine里的错误怎么传递?

sheepbao · 2016年10月14日 · 最后由 themoonstone 回复于 2016年10月14日 · 299 次阅读

首先 goroutine 真的很爽。。。 场景是这样的,就是要把 goroutine 里的错误消息传递出来,简单的代码示例:

func work(some string, ch chan string){
    // do something
    err:=dosomething()
    for{
        select{
        case <-ch:
            // do something
            err:=doOthersome()
        }
    }
}

func main(){
    go work(some, ch)
    //  在这里如何得到work函数里的err
}

我现在用的是在 main 函数里定义一个 chan error,传递给 work,然后在 work 里有 err 的时候,给这个 chan error 发消息,在 main 函数里接收,但这样如果没有 err,会导致 main 函数阻塞。

func work(some string, ch chan string, chanErr chan error){
    // do something
    err:=dosomething()
    if err!=nil{
        chanErr<-err
        return
    }
    for{
        select{
        case <-ch:
            // do something
            err:=doOthersome()
            if err!=nil{
                chanErr<-err
                return
            }
        }
    }
}

func main(){
chanErr:=make(chan error)
    go work(some, ch, chanErr)
    //  在这里接收work函数里的err, 没有任何错误的话会阻塞
    err:=<-chanErr
}

来请教大家,有没有更好的方法?不让 main 函数阻塞

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio

可以参考 https://godoc.org/golang.org/x/sync/errgroup

var g errgroup.Group
var urls = []string{
    "http://www.golang.org/",
    "http://www.google.com/",
    "http://www.somestupidname.com/",
}
for _, url := range urls {
    // Launch a goroutine to fetch the URL.
    url := url // https://golang.org/doc/faq#closures_and_goroutines
    g.Go(func() error {
        // Fetch the URL.
        resp, err := http.Get(url)
        if err == nil {
            resp.Body.Close()
        }
        return err
    })
}
// Wait for all HTTP fetches to complete.
if err := g.Wait(); err == nil {
    fmt.Println("Successfully fetched all URLs.")
}

你这里用的是 select、可以无论有没有产生 err 都给它传值:我贴代码你看一下、测试没问题

package main

import (
    "errors"
    "fmt"
    "math/rand"
    "time"
)

var timeout chan bool

func worker(ch chan int, ch_err chan error) {
    for {
        select {
        case data := <-ch:
            if data%2 != 0 {
                ch_err <- errors.New("ji shu")
                return
            } else {
                ch_err <- nil
            }
        case <-timeout:
            return
        default:
            ch_err <- nil
        }
    }
}

func main() {
    cherr := make(chan error)
    ch := make(chan int)
    data := rand.Int()
    timeout = make(chan bool)

    go worker(ch, cherr)
    go func() {
        ch <- data
        time.Sleep(time.Second)
        timeout <- true
    }()
    fmt.Println(<-cherr)
}

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册