猿问

为什么通道不关闭?

对于以下代码:


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

为什么发件人 go-routine 不关闭通道?


慕桂英3389331
浏览 94回答 1
1回答

翻阅古今

你的maingoroutine 在没有与 emit goroutine 协调的情况下结束以知道它已经完成。当到达结束时main,程序 - 以及它的所有 goroutines - 都会结束,无论是否有任何 goroutine 仍在处理中,除非你明确地等待它们。关闭通道有助于将goroutine 的完成情况传达给. 在这种情况下,使用从通道读取的二值响应,如emitmainword, ok = <-wordChannel确实将通道的状态(打开或关闭)暴露给main,但您从不使用它来控制 main 的流。此外,您有一个确切的硬编码到 main中的读取次数。因此,即使您使用通道关闭来控制流量,您也永远不会尝试最终读取以查看关闭的通道。幸运的是,使用 go 的解决方案非常简单。 range在一个 go 通道上 ing 将读取值,直到通道关闭。因此,您可以简化您的代码,删除通道接收的显式数量,并使用通道 close 来表示emit完成,所有这些都使用这个更简洁的版本:package mainimport "fmt"func emit(c chan string) {&nbsp; &nbsp; words := []string{"The", "quick", "brown", "fox", "ran", "away"}&nbsp; &nbsp; for _, word := range words {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("send %s\n", word)&nbsp; &nbsp; &nbsp; &nbsp; c <- word&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Printf("Close the channel\n")&nbsp; &nbsp; close(c)}func main() {&nbsp; &nbsp; wordChannel := make(chan string)&nbsp; &nbsp; go emit(wordChannel)&nbsp; &nbsp; for word := range wordChannel {&nbsp; &nbsp; &nbsp; fmt.Printf("receive %s \n", word)&nbsp; &nbsp; }}当我运行它时,我得到了我认为是您想要的输出:$ go run t.gosend Thesend quickreceive Thereceive quicksend brownsend foxreceive brownreceive foxsend ransend awayreceive ranreceive awayClose the channel这个“ rangeover a channel”语法在概念上等同于这样的东西,只是看起来更优雅一点:func main() {&nbsp; &nbsp; wordChannel := make(chan string)&nbsp; &nbsp; go emit(wordChannel)&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; if word, ok := <-wordChannel; ok {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("receive %s \n", word)&nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; break&nbsp; &nbsp; &nbsp; }&nbsp; }}
随时随地看视频慕课网APP

相关分类

Go
我要回答