猿问

Sync.WaitGroup,为什么在 goroutine 中更接近

下面是 Go 编程书中的示例代码。我不明白为什么 close 需要是它自己的 goroutine。我试图靠近主,但它崩溃了。有人可以解释为什么更接近的需要在一个单独的 goroutine 中?


谢谢!


func makeThumbnails(filenames <-chan string, result chan<- int64) int64 {

  sizes := make(chan int64)

  var wg sync.WaitGroup

  for f := range filenames {

      wg.Add(1)

      go func(f string) {

        defer wg.Done()

        sizes <- int64(len(f))

      }(f)

  }


  // **closer**, why this guy needs to be in a goroutine???

  go func() {

    wg.Wait()

    close(sizes)

  }()


  var total int64

  for size := range sizes {

    total += size

  }

  result <- total

  return total

}


米琪卡哇伊
浏览 227回答 1
1回答

largeQ

问题是它sizes不是一个 buffered chan,所以只有一个匿名 goroutines 可以在sizes需要读取之前实际完成。这会wg.Wait()导致永远等待(因为下一个 goroutine 正在阻塞sizes <-并且不能defer wg.Done())和死锁。通过将 close 放入单独的 goroutine 中,它可以在sizes准备好时关闭chan,并sizes在两者之间进行处理。最终,这是 goroutine 的一个很好的用途——触发并忘记关闭!为了让这段代码在没有更接近的 goroutine 的情况下工作,你可以简单地初始化sizes为一个缓冲的 chan,缓冲区 >= 的长度filenames。func makeThumbnails(filenames <-chan string, result chan<- int64) int64 {&nbsp; &nbsp; sizes := make(chan int64, 10) // buffered channel, now!&nbsp; &nbsp; // if filenames sends more than 10 strings, though, we're in trouble!!&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; for f := range filenames {&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go func(f string) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sizes <- int64(len(f))&nbsp; &nbsp; &nbsp; &nbsp; }(f)&nbsp; &nbsp; }&nbsp; &nbsp; // **closer**, this guy doesn't need to be a goroutine!!&nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; close(sizes)&nbsp; &nbsp; var total int64&nbsp; &nbsp; for size := range sizes {&nbsp; &nbsp; &nbsp; &nbsp; total += size&nbsp; &nbsp; }&nbsp; &nbsp; result <- total&nbsp; &nbsp; return total}但是,由于filenames的长度在运行时是不可知的,因此不可能轻松做到这一点。你必须通读filenames,将其存储到一个切片,然后初始化大小和for在range filenamesSlice与....是啊基本上你只是重新写在该点的整体功能。
随时随地看视频慕课网APP

相关分类

Go
我要回答