【问题标题】:How to wait for goroutines to finish and read the channel without a lock?如何等待 goroutine 完成并在没有锁的情况下读取通道?
【发布时间】:2018-04-08 21:11:53
【问题描述】:

我在这里查看了一些关于 SO 的示例和问题,但仍然无法让一个相当简单的代码按预期工作:

func main() {
    ch := make(chan string)
    var wg sync.WaitGroup
    wg.Add(2)
    go readFile("A", ch, wg)
    go readFile("B", ch, wg)
    go func() {
        wg.Wait()
        close(ch)
    }()
    printer(ch)
}

func readFile(name string, ch chan string, wg sync.WaitGroup) {
    file, err := os.Open(name)
    if err != nil {
        fmt.Errorf("was not able to read from file %s: %s", name, err)
    }
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        ch <- scanner.Text()
    }
    wg.Done()
}

func printer(ch chan string) {
    for val := range ch {
        fmt.Println(val)
    }
}

所以我从两个文件中读取,将读取的行推送到一个通道中,然后简单地打印出来(一些代码是从不需要的细节中简化的)

两个 goroutine,两个都是 WaitGroup,用 Wait 修复 goroutine 并关闭通道。

从我的角度来看,这与这个问题和 exepted 答案几乎相同:Let golang close used channel after all goroutines finished

那么我的情况有什么问题?

【问题讨论】:

  • 尝试将 WaitGroup 指针传递给 readFile 而不是值。
  • "第一次使用后不得复制 WaitGroup。"请改用指向 WaitGroup 的指针。
  • 运行go vet,或者进行单个单元测试都会立即显示错误。
  • 获取或不获取它们不是问题。问题是我没有看到我正在传递一个值而不是一个指针。
  • 是的,go vet 警告您正在复制该值,go test 运行 go vet

标签: go goroutine


【解决方案1】:

首先遵循sync.WaitGroup 说明的文档:

Package sync

import "sync"

type WaitGroup

WaitGroup 等待一组 goroutine 完成。主要的 goroutine 调用 Add 来设置要等待的 goroutine 的数量。然后 每个 goroutine 运行并在完成时调用 Done。同时 时间,Wait 可以用来阻塞,直到所有的 goroutine 都完成。

WaitGroup 首次使用后不得复制。


WaitGroup 首次使用后不得复制。

【讨论】:

  • >第一次使用后不得复制 WaitGroup。 - 他们应该把它放在盒子上! (c) 罗斯·盖勒
  • @konart,解决此问题的一种方法是正确处理 Go 文档:它尽可能简洁且枯燥,因此您不要略读它——作为一个在我们思考剪辑的时候,通常会处理其他一些文档,但实际上是从上到下阅读。这真的有效,相信我;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-24
  • 2022-08-17
  • 2014-05-15
  • 2019-01-16
  • 2014-01-24
相关资源
最近更新 更多