go - 从不同的 go 例程将数据写入同一 channel ,无需 WaitGroup 即可正常工作

标签 go

在等待 wg.Wait() 后,当使用多个带 WaitGroup 的 go 例程将数据写入同一 channel 时,出现异常,表示所有 go 例程都处于休眠状态或锁死状态。

package main

import (
    "fmt"
    "runtime"
    "sync"
)

var wg sync.WaitGroup

func CreateMultipleRoutines() {
    ch := make(chan int)

    for i := 0; i < 10; i++ { // creates 10 go routines and adds to waitgroup
        wg.Add(1)
        go func() {
            for j := 0; j < 10; j++ {
                ch <- j
            }
            wg.Done() // indication of go routine is done to main routine
        }()
    }

    fmt.Println(runtime.NumGoroutine())
    wg.Wait()           //wait for all go routines to complete
    close(ch)           // closing channel after completion of wait fo go routines
    for v := range ch { // range can be used since channel is closed
        fmt.Println(v)
    }
    fmt.Println("About to exit program ...")
}

当尝试在没有 WaitGroup 的情况下实现这一点时,我能够通过循环将数据推送到 channel 的确切次数从 channel 读取数据,但我无法调整范围,因为当我们关闭 channel 时会出现 panic 。这是示例代码

package main

import (
    "fmt"
    "runtime"
)

func main() {
    ch := make(chan int)


    for i := 0; i < 10; i++ { // creates 10 go routines and adds to waitgroup
        go func(i int) {
            for j := 0; j < 10; j++ {
                ch <- j * i
            }
        }(i)
    }

    fmt.Println(runtime.NumGoroutine())

    for v := 0; v < 100; v++ {
        fmt.Println(<-ch)
    }
    fmt.Println("About to exit program ...")
}

我想了解为什么等待状态下的 WaitGroup 仍在等待,即使所有 go routines 都发出 Done() 信号,这又使 go routines 的数量为零

最佳答案

我认为您的原始代码存在一些问题。

  1. 您正在关闭 channel ,然后再阅读。
  2. 由于您的 channel “大小”为 1,因此您无法获得使用 10 个 goroutine 的优势。所以一个 goroutine 每次产生一个结果。

我的解决方案是生成一个新的 goroutine 来监控 10 个 goroutine 是否完成了它的工作。在那里您将使用您的 WaitGroup

那么代码会是这样的:

package main

import (
    "fmt"
    "runtime"
    "sync"
)

var wg sync.WaitGroup

func main() {
    ch := make(chan int, 10)

    for i := 0; i < 10; i++ { // creates 10 go routines and adds to waitgroup
        wg.Add(1)
        go func() {
            for j := 0; j < 10; j++ {
                ch <- j
            }
            wg.Done() // indication of go routine is done to main routine
        }()
    }

    go func(){
        wg.Wait()
        close(ch)
    }()

    fmt.Println(runtime.NumGoroutine())
    for v := range ch { // range can be used since channel is closed
        fmt.Println(v)
    }
    fmt.Println("About to exit program ...")
}

关于go - 从不同的 go 例程将数据写入同一 channel ,无需 WaitGroup 即可正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55103707/

相关文章:

go - Go例程AWS lambda

go - 为什么我的 Go 指针接收器不会导致更新?

unit-testing - 为从中读取的函数填充 os.Stdin

json - 解码 JSON 值,可以是字符串或数字

go - 以太坊错误 {"code":-32000 ,"message" :"unknown account"}

go - 如何在 Gin 框架中添加后回调

go - Golang中的Google Pay PaymentMethodTokenRecipient函数实现

go - 构建命令行参数 : cannot load local package: cannot find module providing package

go - 以下哪些是 Go 中用于控制循环的有效关键字?

go - Go 中的 strconv.Atoi(基本计算器)