为了账号安全,请及时绑定邮箱和手机立即绑定

为什么通道不关闭?

为什么通道不关闭?

Go
慕桂英3389331 2022-06-01 16:19:16
对于以下代码:package mainimport "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 Thesend quickreceive The receive quick send brownsend foxreceive brown receive fox truesend ransend awayreceive ran truereceive away true为什么发件人 go-routine 不关闭通道?
查看完整描述

1 回答

?
翻阅古今

TA贡献1780条经验 获得超5个赞

你的maingoroutine 在没有与 emit goroutine 协调的情况下结束以知道它已经完成。当到达结束时main,程序 - 以及它的所有 goroutines - 都会结束,无论是否有任何 goroutine 仍在处理中,除非你明确地等待它们。


关闭通道有助于将goroutine 的完成情况传达给. 在这种情况下,使用从通道读取的二值响应,如emitmain


word, ok = <-wordChannel

确实将通道的状态(打开或关闭)暴露给main,但您从不使用它来控制 main 的流。此外,您有一个确切的硬编码到 main中的读取次数。因此,即使您使用通道关闭来控制流量,您也永远不会尝试最终读取以查看关闭的通道。


幸运的是,使用 go 的解决方案非常简单。 range在一个 go 通道上 ing 将读取值,直到通道关闭。因此,您可以简化您的代码,删除通道接收的显式数量,并使用通道 close 来表示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

这个“ rangeover a channel”语法在概念上等同于这样的东西,只是看起来更优雅一点:


func main() {

    wordChannel := make(chan string)

    go emit(wordChannel)

    for {

      if word, ok := <-wordChannel; ok {

        fmt.Printf("receive %s \n", word)

      } else {

        break

      }

  }

}


查看完整回答
反对 回复 2022-06-01
  • 1 回答
  • 0 关注
  • 93 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号