为了账号安全,请及时绑定邮箱和手机立即绑定

编写此代码的更好的惯用方式?

编写此代码的更好的惯用方式?

Go
慕田峪7331174 2021-06-03 14:50:10
玩转 go,我把这段代码放在一起:package mainimport "fmt"const N = 10func main() {    ch := make(chan int, N)    done := make(chan bool)    for i := 0; i < N; i++ {        go (func(n int, ch chan int, done chan bool) {            for i := 0; i < N; i++ {                ch <- n*N + i            }            done <- true        })(i, ch, done)    }    numDone := 0    for numDone < N {        select {        case i := <-ch:            fmt.Println(i)        case <-done:            numDone++        }    }    for {        select {        case i := <-ch:            fmt.Println(i)        default:            return        }    }}基本上我有 N 个频道在做一些工作并在同一个频道上报告——我想知道所有频道什么时候完成。所以我有另一个done通道,每个工作程序 goroutine 都会在其上发送一条消息(消息无关紧要),这会导致 main 将该线程计为已完成。当计数达到 N 时,我们实际上就完成了。这是“好”吗?有没有更惯用的方式来做到这一点?编辑:澄清一下,我很怀疑,因为done通道似乎正在做一个通道关闭似乎是为了的工作,但当然我实际上不能在任何 goroutine 中关闭通道,因为所有的例程共享同一个通道. 所以我done用来模拟一个执行某种“缓冲关闭”的通道。编辑2:原始代码并没有真正起作用,因为有时在done它刚刚放入的 int 之前读取来自例程的信号ch。需要一个“清理”循环。
查看完整描述

3 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

这里是sync.WaitGroup的惯用用法,供大家学习

package main


import (

    "fmt"

    "sync"

)


const N = 10


func main() {

    ch := make(chan int, N)

    var wg sync.WaitGroup

    for i := 0; i < N; i++ {

        wg.Add(1)

        go func(n int) {

            defer wg.Done()

            for i := 0; i < N; i++ {

                ch <- n*N + i

            }

        }(i)

    }

    go func() {

        wg.Wait()

        close(ch)

    }()

    for i := range ch {

        fmt.Println(i)

    }

}

注意两个go例程定义中闭包的使用,注意第二条go语句等待所有例程完成,然后关闭通道,所以range可以使用。


查看完整回答
反对 回复 2021-06-07
  • 3 回答
  • 0 关注
  • 224 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信