¿Un canal devuelve dos valores?
Frecuentes
Visto 24,004 veces
28
Vi un código en este enlace y me confundí:http://www.darkcoding.net/software/go-lang-after-four-months/
¿Cuál es el significado del segundo valor (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
}
}
}
4 Respuestas
33
La variable booleana ok
devuelto por un recibir operador indica si el valor recibido se envió en el canal (verdadero) o se devuelve un valor cero porque el canal está cerrado y vacío (falso).
La for
bucle termina cuando alguna otra parte del programa Go cierra el fromServer
o fromUser
canal. En ese caso, una de las sentencias case establecerá ok
a la verdad Entonces, si el usuario cierra la conexión o el servidor remoto cierra la conexión, el programa terminará.
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")
}
Respondido el 23 de enero de 16 a las 21:01
¿Qué significa vacío en este caso? Cerrado es fácil, pero ¿vacío significa que nadie está escribiendo en este momento? - Kr0e
@Kr0e Si un canal está cerrado pero aún contiene algunos elementos que es posible recibir de él y ok
is true
. Pero es imposible escribir en un canal cerrado (de hecho, esta es una definición de "canal cerrado"). Cuando un canal había sido cerrado por el productor goroutine y drenado por el consumidor que ok
is false
. Vacío y cerrado, como decía. - I159
11
Un par de respuestas han citado la especificación en el operador de recepción, pero para comprender probablemente necesite leer la especificación en el función de cierre también. Luego, dado que se estará preguntando por qué estas características son como son, lea cómo para declaración rangos sobre un canal. La instrucción for necesita una señal para detener la iteración y close
es la forma en que un remitente puede decir "no más datos".
Con close
y , ok = <-
expuestos como parte del idioma, puede usarlos en otros casos cuando desee que una rutina de envío señale "no más datos". El código de ejemplo en la pregunta es un uso interesante de estas funciones. Está manejando tanto un canal de "servidor" como un canal de "usuario", y si llega una señal de "no más datos" de ya sea de ellos, se sale del bucle.
contestado el 03 de mayo de 12 a las 21:05
Tiene toda la razón. La operación de recepción de valores múltiples devuelve un valor recibido junto con una indicación de si el canal está cerrado. - pase duro
2
Consulte la sección correspondiente en las especificaciones de idioma de Go: http://golang.org/ref/spec#Receive_operator
contestado el 03 de mayo de 12 a las 20:05
-1
En Go, las funciones y los canales pueden devolver más de 1 valor. Aquí ok debe ser una variable booleana con verdadero (correcto) y falso (incorrecto) y serverData son los datos reales recibidos del canal.
contestado el 03 de mayo de 12 a las 19:05
Esa es la misma construcción para los mapas. - Denys Séguret
Todavía estoy confundido. No entiendo cuando el segundo retorno es falso? Creo que si un canal está vacío, se bloqueará. Y si un canal no está bloqueado, debe volver con éxito. - pase duro
para aclarar eso, supongo que necesitamos ver más del código, es decir, qué está haciendo realmente el canal fromServer, etc. - Caos
@hardPass: devolverá falso si el canal es cerrado y vacío- nuevoacct
@Chaos, estás equivocado. Los canales no pueden recibir ni emitir valores múltiples. - nathan dulce
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas go channel or haz tu propia pregunta.
Me parece que es una construcción demasiado pesada. Con select, creo que no hay necesidad de buscar el booleano ok. O me estoy perdiendo algo ? - Denys Séguret
son ortogonales. "ok" en la operación de recepción del canal indica si el canal está cerrado. Select solo espera hasta que al menos uno de sus casos pueda ejecutarse, y luego elige uno al azar sin importar si el canal está cerrado. Un caso predeterminado hace que no bloquee. - SteveMcQwark