Does a channel return two values?

hardPass picture hardPass · May 3, 2012 · Viewed 20.8k times · Source

I saw some code in this link, and got confused:http://www.darkcoding.net/software/go-lang-after-four-months/

What's the meaning of the second value(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
        }
    }

}

Answer

user811773 picture user811773 · May 3, 2012

The boolean variable ok returned by a receive operator indicates whether the received value was sent on the channel (true) or is a zero value returned because the channel is closed and empty (false).

The for loop terminates when some other part of the Go program closes the fromServer or the fromUser channel. In that case one of the case statements will set ok to true. So if the user closes the connection or the remote server closes the connection, the program will terminate.

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")
}