Does a channel return two values?
See the relevant section in the Go language spec: http://golang.org/ref/spec#Receive_operator
A couple of answers have cited the spec on the receive operator, but to understand you probably need to read the spec on the close function as well. Then since you'll be wondering why these features are the way they are, read how the for statement ranges over a channel. The for statement needs a signal to stop iteration and close
is the way a sender can say "no more data".
With close
and , ok = <-
exposed as part of the language, you can use them in other cases when you wish a sending goroutine to signal "no more data". The example code in the question is an interesting use of these features. It is handling both a "server" channel and a "user" channel, and if a "no more data" signal arrives from either of them, it breaks out of the loop.
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")
}