2012-05-03 18 views
14

Vi un código en este enlace y me confundí: http://www.darkcoding.net/software/go-lang-after-four-months/¿El canal de Go devuelve dos valores?

¿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 
     } 
    } 

} 
+0

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 ? –

+1

Son ortogonales. "ok" en la operación de recepción de canal indica si el canal está cerrado. Select simplemente espera hasta que se ejecute al menos uno de sus casos, y luego elige uno al azar sin importar si el canal está cerrado. Un caso predeterminado lo hace no bloqueante. – SteveMcQwark

Respuesta

14

La variable booleana ok devuelto por un receive operator indica si el valor recibido fue enviado en el canal (verdadero) o es un valor nulo devuelto porque el canal está cerrado y vacío (falso).

El ciclo for finaliza cuando alguna otra parte del programa Go cierra el canal fromServer o fromUser. En ese caso, una de las declaraciones de casos establecerá ok en verdadero. 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") 
} 
+0

¿Qué significa vacío en este caso? Cerrado es fácil, pero ¿vacío significa que nadie está escribiendo en este momento? – Kr0e

+0

@ Kr0e Si un canal está cerrado pero todavía contiene algunos elementos, es posible recibirlo y 'ok' es 'verdadero'. Pero es imposible escribir en un canal cerrado (de hecho, esta es una definición de "canal cerrado"). Cuando un canal ha sido cerrado por el productor goroutine y drenado por el consumidor que 'ok' es' falso'. Vacío y cerrado, como dijo. – I159

-1

En Go, funciones & canales pueden devolver más de 1 valor. Aquí está bien debe ser una variable booleana con verdadero (exitoso) y falso (sin éxito) y serverData es la información real recibida del canal.

+3

Esa es la misma construcción para los mapas. –

+0

Todavía estoy confundido. No entiendo cuando el segundo retorno es falso? Creo que si un canal está vacío, bloqueará. Y si un canal no está bloqueado, debe regresar exitosamente. – hardPass

+0

para aclarar eso, supongo que necesitamos ver más código, es decir, qué es realmente el canal del servidor, etc. – Chaos

8

Un par de respuestas han citado las especificaciones del operador de recibir, sino entender que probablemente necesita leer la especificación en la close function también. Entonces, como se preguntará por qué estas características son las que son, lea cómo el for statement abarca un canal. La instrucción for necesita una señal para detener la iteración y close es la forma en que un emisor puede decir "no más datos".

Con close y , ok = <- expuestos como parte del idioma, puede usarlos en otros casos cuando desee que un envío de rutina envíe "No más datos". El código de ejemplo en la pregunta es un uso interesante de estas características. Está manejando tanto un canal de "servidor" como un canal de "usuario", y si una señal de "no más datos" llega desde o bien de ellos, se rompe el ciclo.

+0

Tienes toda la razón.La operación de recepción multivalor devuelve un valor recibido junto con una indicación de si el canal está cerrado. – hardPass

Cuestiones relacionadas