为什么通道没有被关闭?[重复]

问题描述 投票:-2回答:1

对于下面的代码。

package main

import "fmt"

func emit(c chan string) {
    words := []string{"The", "quick", "brown", "fox", "ran", "away"}

    for _, word := range words {
        fmt.Printf("send %s\n", word)
        c <- word
    }
    fmt.Printf("Close the channel\n")
    close(c)
}

func main() {
    wordChannel := make(chan string)

    go emit(wordChannel)

    word := <-wordChannel
    fmt.Printf("receive %s \n", word)

    word = <-wordChannel
    fmt.Printf("receive %s \n", word)

    word = <-wordChannel
    fmt.Printf("receive %s \n", word)

    word, ok := <-wordChannel
    fmt.Printf("receive %s %t\n", word, ok)

    word, ok = <-wordChannel
    fmt.Printf("receive %s %t\n", word, ok)

    word, ok = <-wordChannel
    fmt.Printf("receive %s %t\n", word, ok)

}

下面是输出。

send The
send quick
receive The 
receive quick 
send brown
send fox
receive brown 
receive fox true
send ran
send away
receive ran true
receive away true

为什么sender go-routine没有关闭通道?

go channel goroutine
1个回答
1
投票

您的"..."。main goroutine结束时,不需要与emit goroutine协调就可以知道它已经结束了。 当 main 的时候,程序和它的所有goroutines都会结束,不管是否有任何go例程还在处理,除非你明确地等待它们。

关闭通道 可以 有助于传达 emit 戈鲁丁的完成情况 main. 在这种情况下,并使用从通道读取的两个值响应,如在

word, ok = <-wordChannel

是否 将通道的状态(打开或关闭)暴露给 main但你从来没有用它来控制main的流量。 此外,你有一个 确切 读数 暗码 入主。 所以,即使你 用通道关闭来控制流量,你永远不会尝试最终读取来查看关闭的通道。

幸运的是,go的解决方案非常简单。 range在一个go通道上进行读取,直到通道关闭。 因此,你可以简化你的代码,去掉显式的通道接收数,用通道关闭来表示。emit的完成,都用这个更简洁的版本。

package main

import "fmt"

func emit(c chan string) {
    words := []string{"The", "quick", "brown", "fox", "ran", "away"}

    for _, word := range words {
        fmt.Printf("send %s\n", word)
        c <- word
    }
    fmt.Printf("Close the channel\n")
    close(c)
}

func main() {
    wordChannel := make(chan string)
    go emit(wordChannel)
    for word := range wordChannel {
      fmt.Printf("receive %s \n", word)
    }
}

当我运行这个时,我得到了我认为是你想要的输出。

$ go run t.go
send The
send quick
receive The
receive quick
send brown
send fox
receive brown
receive fox
send ran
send away
receive ran
receive away
Close the channel

这个"range 在一个 channel"语法在概念上相当于这样的东西,只是看起来更优雅一些。

func main() {
    wordChannel := make(chan string)
    go emit(wordChannel)
    for {
      if word, ok := <-wordChannel; ok {
        fmt.Printf("receive %s \n", word)
      } else {
        break
      }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.