dousi4257 2013-04-15 16:40
浏览 20
已采纳

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

Playing around with go, I threw together this code:

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
        }
    }
}

Basically I have N channels doing some work and reporting it on the same channel -- I want to know when all the channels are done. So I have this other done channel that each worker goroutine sends a message on (message doesn't matter), and this causes main to count that thread as done. When the count gets to N, we're actually done.

Is this "good" go? Is there a more go-idiomatic way of doing this?

edit: To clarify a bit, I'm doubtful because the done channel seems to be doing a job that channel closing seems to be for, but of course I can't actually close the channel in any goroutine because all the routines share the same channel. So I'm using done to simulate a channel that does some kind of "buffered closing".

edit2: Original code wasn't really working since sometimes the done signal from a routine was read before the int it just put on ch. Needs a "cleanup" loop.

  • 写回答

6条回答 默认 最新

  • dongpu1908 2013-04-15 18:43
    关注

    Here is an idiomatic use of sync.WaitGroup for you to study

    (playground link)

    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)
        }
    }
    

    Note the use of closures in the two go routine definitions and note the second go statement to wait for all the routines to finish, then close the channel, so range can be used.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

悬赏问题

  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥15 stable diffusion
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿