Idiomáticas manera de hacer la conversión/tipo de afirmación en varios valores de retorno en Ir

¿Cuál es la idiomáticas manera para lanzar múltiples valores de retorno en Ir?

Se puede hacer en una sola línea, o usted necesita el uso de variables temporales como yo he hecho en mi ejemplo de abajo?

package main

import "fmt"

func oneRet() interface{} {
    return "Hello"
}

func twoRet() (interface{}, error) {
    return "Hejsan", nil
}

func main() {
    //With one return value, you can simply do this
    str1 := oneRet().(string)
    fmt.Println("String 1: " + str1)

    //It is not as easy with two return values
    //str2, err := twoRet().(string) //Not possible
    //Do I really have to use a temp variable instead?
    temp, err := twoRet()
    str2 := temp.(string)
    fmt.Println("String 2: " + str2 )


    if err != nil {
        panic("unreachable")
    }   
}

Por cierto, se llama casting cuando se trata de interfaces?

i := interface.(int)
InformationsquelleAutor ANisus | 2012-07-09

4 Kommentare

  1. 67

    Usted no puede hacerlo en una sola línea.
    Su temporal de la variable de enfoque es el camino a seguir.

    Por cierto, se llama casting cuando se trata de interfaces?

    Se llama en realidad un tipo de afirmación.
    Un tipo de reparto conversión es diferente:

    var a int
    var b int64
    
    a = 5
    b = int64(a)
  2. 29
    func silly() (interface{}, error) {
        return "silly", nil
    }
    
    v, err := silly()
    if err != nil {
        //handle error
    }
    
    s, ok := v.(string)
    if !ok {
        //the assertion failed.
    }

    pero lo más probable es lo que realmente quieres es usar un tipo de interruptor, como-un-este:

    switch t := v.(type) {
    case string:
        //t is a string
    case int :
        //t is an int
    default:
        //t is some other type that we didn't name.
    }

    Ir es en realidad más acerca de la exactitud que se trata de laconismo.

    • Todavía creo que Vaya logra ser bastante escueto así, sin renunciar a la corrección. Para otros que ven a esta pregunta, creo que es bueno que usted ha mencionado la comprobación de aserción. En mi caso, aunque yo ya sé de qué tipo es almacenado en la interfaz, por lo que me he saltado el cheque. Incluso llegué a pensar sobre el uso de un unsafe.Pointer en lugar de interface{}, pero supuse que no hay suficiente sobrecarga en el tipo de afirmación que justifica el uso de los punteros.
    • Probablemente debería señalar, que el idiomáticas manera de hacer esto es para no volver interfaz{}, pero a aceptar la interfaz{} como un parámetro de entrada, compruebe el tipo que se pasó, y luego llenar ese tipo. Esto se ejemplifica muy bien en la codificación/json del paquete Deserializar método. Estas técnicas no cubren todas las situaciones, por lo que no siempre puede ser posible, pero en general es mejor aceptar la interfaz{} que es devolver la interfaz{}. Usted puede utilizar el reflejo paquete para comprobar para asegurarse de que el valor proporcionado es un puntero.
  3. 12

    de la plantilla.Debe es el estándar de la biblioteca de enfoque de solo devuelve el primer valor de retorno en una declaración. Se podría hacer lo mismo para su caso:

    func must(v interface{}, err error) interface{} {
        if err != nil {
            panic(err)
        }
        return v
    }
    
    //Usage:
    str2 := must(twoRet()).(string)

    Mediante must que, básicamente, decir que no debe ser nunca un error, y si la hay, entonces el programa no se puede (o al menos no debería) mantener operativo, y el pánico en su lugar.

    • Es unidiomatic a entrar en pánico acerca de los errores que no fueron causados por un programador. Una función como template.Must() se utiliza normalmente para la carga de plantillas a partir de una variable en el nivel de paquete de declaraciones y init() funciones. La idea es de pánico inmediatamente en tiempo de ejecución y haga evidente que algo de lo que el compilador no podía atrapar está mal. Usted no debe usar este para evitar variables temporales.
    • Y que parte de la «mediante el uso de must que, básicamente, decir que no debe ser nunca un error» no estaba claro? Usted no debe usar este, a menos que el error sólo puede ser causada por un programador o el programa realmente no puede continuar si hay un error.
    • No estoy de acuerdo con «o el programa realmente no puede continuar si hay un error». En el caso de que usted todavía no debe entrar en pánico.
    • Ni siquiera es un argumento, ya que en su mayoría están de acuerdo con que uno. Es sólo idiomáticas, si usted no puede o no desea registrar el error. Así que rara vez idiomáticas.
    • Pero, en su 1er comentario, ¿por qué se supone que yo dijo es idiomático de pánico en los errores que no fueron causados por un programador?
    • Mientras veo a Esteban punto, la respuesta sigue siendo útil en algunos casos (como Stephen señaló también). Gracias por el contenedor de pensamiento.
    • Vale la pena mencionar que en las pruebas, debe (a) al igual que la escritura es es a la mano. Gomega tiene buen atajo para esto: onsi.github.io/gomega/#de manejo de errores. Sin embargo, si se bloquea la prueba, usted necesita para recuperar y tener cuidado acerca de la limpieza. Gomega ha conectables «no controlador»; Ginkgo proporciona el pánico, la recuperación (onsi.github.io/ginkgo/#marca-especificaciones-como-error), y AfterEach/AfterSuite bloques para la limpieza.

  4. 10

    O simplemente en una sola si:

    if v, ok := value.(migrater); ok {
        v.migrate()
    }

    Será el reparto dentro de la cláusula if y permiten acceder a las propiedades de la escayola tipo.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea