82 votes

Manière idiomatique de faire une conversion / une assertion de type sur plusieurs valeurs de retour dans Go

Quelle est la manière idiomatique de convertir plusieurs valeurs de retour dans Go?

Pouvez-vous le faire en une seule ligne ou devez-vous utiliser des variables temporaires telles que celles décrites dans l'exemple ci-dessous?

 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("Not nil? Impossiburu!")
    }   
}
 

À propos, est-ce que cela s'appelle casting en ce qui concerne les interfaces?

 i := interface.(int)
 

70voto

jimt Points 7028

Vous ne pouvez pas le faire en une seule ligne. Votre approche variable temporaire est la voie à suivre.

À propos, est-ce que ça s'appelle casting quand il s'agit d'interfaces?

C'est ce qu'on appelle une assertion de type . Une conversion de fonte de type différent:

 var a int
var b int64

a = 5
b = int64(a)
 

38voto

jorelli Points 2494
 func silly() (interface{}, error) {
    return "silly", nil
}

v, err := silly()
if err != nil {
    // handle error
}

s, ok := v.(string)
if !ok {
    // the assertion failed.
}
 

mais il est plus probable que vous souhaitiez réellement utiliser un commutateur de type, comme ceci:

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

Go est vraiment plus une question de correction que de concision.

12voto

Zippoxer Points 2271

template.Must est l'approche de la bibliothèque standard pour renvoyer uniquement la première valeur renvoyée dans une instruction. Pourrait être fait de la même manière pour votre cas:

 func must(v interface{}, err error) interface{} {
    if err != nil {
        panic(err)
    }
    return v
}

// Usage:
str2 := must(twoRet()).(string)
 

En utilisant must vous dites en gros qu'il ne devrait jamais y avoir d'erreur, et s'il y en a, alors le programme ne peut pas (ou du moins ne devrait pas) continuer à fonctionner, et paniquera à la place.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X