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

玩转 go,我把这段代码放在一起:


package main


import "fmt"


const N = 10


func 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。需要一个“清理”循环。


慕田峪7331174
浏览 225回答 3
3回答

海绵宝宝撒

这里是sync.WaitGroup的惯用用法,供大家学习package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "sync")const N = 10func main() {&nbsp; &nbsp; ch := make(chan int, N)&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; for i := 0; i < N; i++ {&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go func(n int) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for i := 0; i < N; i++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ch <- n*N + i&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }(i)&nbsp; &nbsp; }&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; &nbsp; &nbsp; close(ch)&nbsp; &nbsp; }()&nbsp; &nbsp; for i := range ch {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(i)&nbsp; &nbsp; }}注意两个go例程定义中闭包的使用,注意第二条go语句等待所有例程完成,然后关闭通道,所以range可以使用。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go