【问题标题】:Does a channel return two values?通道是否返回两个值?
【发布时间】:2012-05-13 07:13:04
【问题描述】:

我在这个链接里看到了一些代码,一头雾水:http://www.darkcoding.net/software/go-lang-after-four-months/

第二个值(ok)是什么意思?

for self.isRunning {

    select {
    case serverData, ok = <-fromServer:   // What's the meaning of the second value(ok)?
        if ok {
            self.onServer(serverData)
        } else {
            self.isRunning = false
        }

    case userInput, ok = <-fromUser:
        if ok {
            self.onUser(userInput)
        } else {
            self.isRunning = false
        }
    }

}

【问题讨论】:

  • 在我看来这是一个过于沉重的结构。使用 select,我认为没有必要获取 ok 布尔值。还是我错过了什么?
  • 它们是正交的。通道接收操作中的“ok”表示通道是否关闭。 Select 只是等到它的至少一个 case 可以运行,然后随机选择一个而不考虑 channel 是否关闭。默认情况下使其非阻塞。

标签: go channel


【解决方案1】:

receive operator 返回的布尔变量 ok 表示接收到的值是在通道上发送的 (true) 还是因为通道关闭且为空而返回的零值 (false)。

当 Go 程序的其他部分关闭 fromServerfromUser 通道时,for 循环终止。在这种情况下,case 语句之一会将ok 设置为true。所以如果用户关闭连接或者远程服务器关闭连接,程序就会终止。

http://play.golang.org/p/4fJDkgaa9O:

package main

import "runtime"

func onServer(i int) { println("S:", i) }
func onUser(i int)   { println("U:", i) }

func main() {
    fromServer, fromUser := make(chan int),make(chan int)
    var serverData, userInput int
    var ok bool

    go func() {
        fromServer <- 1
        fromUser <- 1
        close(fromServer)
        runtime.Gosched()
        fromUser <- 2
        close(fromUser)
    }()

    isRunning := true
    for isRunning {
        select {
            case serverData, ok = <-fromServer:
                if ok {
                    onServer(serverData)
                } else {
                    isRunning = false
                }

            case userInput, ok = <-fromUser:
                if ok {
                    onUser(userInput)
                } else {
                    isRunning = false
                }
            }
        }
        println("end")
}

【讨论】:

  • 在这种情况下,空是什么意思?关闭很容易,但是空的是否意味着现在没有人在写??
  • @Kr0e 如果通道已关闭但仍包含一些项目,则可以从中接收,oktrue。但是不可能写入一个封闭的通道(这实际上是“封闭通道”的定义)。当通道被生产者 goroutine 关闭并被消费者耗尽时,okfalse。就像它说的那样,空的和封闭的。
【解决方案2】:

一些答案​​引用了接收运算符的规范,但要了解您可能还需要阅读 close function 上的规范。然后,既然您会想知道为什么这些功能是这样的,请阅读for statement 是如何在一个频道上覆盖的。 for 语句需要一个信号来停止迭代,close 是发送者可以说“没有更多数据”的方式。

close, ok = &lt;- 作为语言的一部分公开,当您希望发送 goroutine 发出“没有更多数据”信号时,可以在其他情况下使用它们。问题中的示例代码是对这些功能的有趣使用。它同时处理“服务器”通道和“用户”通道,如果“没有更多数据”信号从任何一个到达,它就会跳出循环。

【讨论】:

  • 你完全正确。多值接收操作返回一个接收值以及通道是否关闭的指示。
【解决方案3】:

请参阅 Go 语言规范中的相关部分: http://golang.org/ref/spec#Receive_operator

【讨论】:

    【解决方案4】:

    在 Go 中,函数和通道可以返回超过 1 个值。这里 ok 必须是一个布尔变量,具有 true(成功)和 false(不成功),serverData 是从通道接收到的实际数据。

    【讨论】:

    • 地图的构造是一样的。
    • 我还是一头雾水。我不明白第二次返回什么时候是假的?我认为如果一个通道是空的,它会阻塞。如果一个通道没有被阻塞,它必须成功返回。
    • 为了澄清这一点,我想我们需要查看更多代码,即来自服务器的通道实际上在做什么等等。
    • @hardPass:如果频道关闭并且为空,它将返回false
    • @Chaos,你错了。通道不能接收或发出多个值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 2014-06-14
    • 1970-01-01
    • 2021-04-23
    • 2023-03-28
    • 2019-10-06
    相关资源
    最近更新 更多