从多个渠道读取错误

像许多 go 程序员一样,到目前为止都避免对通道做任何重要的事情,所以这个看似简单的场景让我感到难过!


我希望多个 goroutines 发送由单亲检查的结果。如果有任何发送错误,父母应该发出信号让他们全部停止。父母应该不按顺序阅读结果。


如果其中一个 goroutine 确实发送错误,则此代码有效,即如果您在11内部 nums 中发表评论,否则我们将永远陷入 for 循环。


func main() {

    type Result struct {

        Error    error

        Response int

    }

    checkStatus := func(done <-chan interface{}, ns []int) <-chan Result {

        results := make(chan Result)

        go func() {

            defer close(results)

            for _, n := range ns {

                result := Result{Response: n}

                if n == 11 {

                    result.Error = fmt.Errorf("problem...\n")

                }

                select {

                case <-done:

                    return

                case results <- result:

                }

            }

        }()

        return results

    }


    done := make(chan interface{})

    defer close(done)


    nums := []int{1, 2, 3, 4, 5 /*11,*/, 6, 7, 8, 9, 10}

    c1 := checkStatus(done, nums[:5])

    c2 := checkStatus(done, nums[5:])

    for {

        var r Result

        select {

        case r = <-c1:

            if r.Error != nil {

                fmt.Printf("error1: %v", r.Error)

                return

            }

            fmt.Printf("Response1: %v\n", r.Response)

        case r = <-c2:

            if r.Error != nil {

                fmt.Printf("error2: %v", r.Error)

                return

            }

            fmt.Printf("Response2: %v\n", r.Response)

        }

    }

}

我能看到修复它的唯一方法是更改for循环,以便它从中读取c1,c2但我看不到非顺序执行此操作的方法?


https://go.dev/play/p/7dRPMDn1Za2


海绵宝宝撒
浏览 105回答 1
1回答

函数式编程

您正在从封闭的渠道中阅读,他们总是返回零值。您可以做的是在从通道读取时使用逗号 ok 习惯用法关闭选择案例,然后将通道分配给 nil。如果另一个也为零,则返回。case使用 nil 通道永远不会运行。只需扩展您的代码(与 的情况类似c2):case r, ok := <-c1:&nbsp; &nbsp; if !ok {&nbsp; &nbsp; &nbsp; &nbsp; c1 = nil&nbsp; &nbsp; &nbsp; &nbsp; if c2 == nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; }&nbsp; &nbsp; if r.Error != nil {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("error1: %v", r.Error)&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Printf("Response1: %v\n", r.Response)但我宁愿尝试重构整个实现。您可以考虑使用sync.WaitGroup来自syncpkg 或errgroup.Group来自errgrouppkg.
打开App,查看更多内容
随时随地看视频慕课网APP