2016-08-16 1 views
4

Lassen Sie uns sagen, ich habe dies:Golang: Können Sie eine zurückgegebene Schnittstelle {} in einer Anweisung eingeben?

type Donut string 
type Muffin string 

func getPastry() (interface{}, error) { 
    // some logic - this is contrived 
    var d Donut 
    d = "Bavarian" 
    return d, nil 
} 

Ist es möglich, diese Linie auf einen zu reduzieren:

p, err := getPastry() 
thisPastry := p.(Donut) 

Mit anderen Worten, so etwas wie dieses, die nicht kompiliert:

thisPastry, err := getPastry().(Donut, error) 

Nicht, dass zwei Zeilen Code, um das "generische" und geben Sie es ist eine große Sache, aber es fühlt sich einfach verschwenderisch und un-einfach für mich, und das bedeutet in der Regel bedeutet, ich vermisse etwas obvio uns :-)

Antwort

7

Sie können nicht. Beste, was Sie tun können, ist eine Hilfsfunktion schreiben (und tun die Art Behauptung, dass):

func getDonut(p interface{}, err error) (Donut, error) { 
    return p.(Donut), err 
} 

Und dann wird es eine einzeilige:

d, err := getDonut(getPastry()) 

Oder Sie können sogar „übernehmen“ die getPastry() Aufruf in der Hilfsfunktion:

func getDonutPastry() (Donut, error) { 
    p, err := getPastry() 
    return p.(Donut), err 
} 

Und dann nennt es (ein noch kürzerer Einzeiler):

d, err := getDonutPastry() 

Hinweis:

Natürlich, wenn der von getPastry() zurückgegebene Wert nicht von dynamischem Typ Donut ist, wird dies eine Laufzeit Panik sein. Um zu verhindern, dass können Sie die spezielle Form des type assertion verwenden:

v, ok := x.(T) 

, die einen zusätzlichen untypisierten boolean Wert liefert. Der Wert ok ist true, wenn die Behauptung gilt. Ansonsten ist es false und der Wert v ist der Nullwert für den Typ T. In diesem Fall tritt keine Laufzeitpanik auf.

Sichere Versionen der Hilfsfunktionen, die spezielle Form verwenden könnte wie folgt aussehen (sie einen Fehler zurück, anstatt Panik):

func getDonut2(p interface{}, err error) (Donut, error) { 
    if d, ok := p.(Donut); ok { 
     return d, err 
    } else { 
     return "", errors.New("Not a Donut!") 
    } 
} 

func getDonutPastry2() (Donut, error) { 
    p, err := getPastry() 
    if d, ok := p.(Donut); ok { 
     return d, err 
    } else { 
     return "", errors.New("Not a Donut!") 
    } 
} 

Siehe Fragen:

Return map like 'ok' in Golang on normal functions

Go: multiple value in single-value context

+2

IMO dieses Beispiel zeigt schlechte Praxis, wie wir ohne zu prüfen, für einen Fehler eine Art Behauptung machst, wo die Umbruchfunktion den Eindruck erweckt, dass sie Fehler zurückgibt und keine Panik auslöst. – baloo

+0

@baloo Siehe bearbeitete Antwort. – icza

+0

gute zusätzliche Hinweise! – baloo

4

Kurze Antwort: Es ist nicht möglich.

Lange Antwort:
Es wird für mehr Leute lesbarer und verständlicher sein, da es keine langen Linien gibt, die viele Dinge miteinander verketten.

In Ihrem Beispiel nehme ich an, dass Sie auf einen Fehler prüfen müssen und dann nach einem Muffin usw. suchen müssen. Um deutlich zu machen, Super welche Arten Sie erwarten und was mit ihnen zu tun, können Sie eine Art Schalter tun können:

thisPastry, err := getPastry() 
if err != nil { ... } 

switch v := thisPastry.(type) { 
case Donut: 
    fmt.Println(v) 
case Muffin: 
    fmt.Println(v, "mmm!") 
default: 
    // some kind of error? 
} 
Verwandte Themen