it-swarm.com.de

Daten (Typ interface {}) können nicht in Typ string konvertiert werden: Typzusicherung erforderlich

Ich bin noch ziemlich neu und habe mit diesem notify -Paket gespielt.

Zuerst hatte ich Code, der so aussah:

func doit(w http.ResponseWriter, r *http.Request) {
    notify.Post("my_event", "Hello World!")
    fmt.Fprint(w, "+OK")
}

Ich wollte newline an Hello World! Anhängen, aber nicht in der obigen Funktion doit, weil das ziemlich trivial wäre, sondern in der folgenden handler:

func handler(w http.ResponseWriter, r *http.Request) {
    myEventChan := make(chan interface{})
    notify.Start("my_event", myEventChan)
    data := <-myEventChan
    fmt.Fprint(w, data + "\n")
}

Nach go run:

$ go run lp.go 
# command-line-arguments
./lp.go:15: invalid operation: data + "\n" (mismatched types interface {} and string)

Nach ein wenig googeln fand ich diese Frage auf SO .

Dann habe ich meinen Code aktualisiert:

func handler(w http.ResponseWriter, r *http.Request) {
    myEventChan := make(chan interface{})
    notify.Start("my_event", myEventChan)
    data := <-myEventChan
    s:= data.(string) + "\n"
    fmt.Fprint(w, s)
}

Sollte ich das tun? Meine Compilerfehler sind weg, also denke ich, dass das ziemlich gut ist? Ist das effizient? Solltest du es anders machen?

155
Alfred

Nach der Go-Spezifikation :

Für einen Ausdruck x vom Schnittstellentyp und einen Typ T gibt der primäre Ausdruck x. (T) an, dass x nicht null ist und dass der in x gespeicherte Wert vom Typ T ist.

Mit einer "Typzusicherung" können Sie deklarieren, dass ein Schnittstellenwert einen bestimmten konkreten Typ enthält oder dass sein konkreter Typ einer anderen Schnittstelle entspricht.

In Ihrem Beispiel haben Sie angegeben, dass Daten (Typ interface {}) den konkreten Typ string haben. Wenn Sie sich irren, kommt das Programm zur Laufzeit in Panik. Sie müssen sich keine Gedanken über die Effizienz machen. Für die Überprüfung müssen lediglich zwei Zeigerwerte verglichen werden.

Wenn Sie sich nicht sicher sind, ob es sich um eine Zeichenfolge handelt, können Sie die Syntax mit zwei Rückgaben testen.

str, ok := data.(string)

Wenn es sich bei den Daten nicht um eine Zeichenfolge handelt, ist ok false. Es ist dann üblich, eine solche Anweisung in eine if-Anweisung wie folgt zu verpacken:

if str, ok := data.(string); ok {
    /* act on str */
} else {
    /* not string */
}
273

Geben Sie Assertion ein

Dies wird in Golang als type assertion Bezeichnet und ist eine gängige Praxis.

Hier ist die Erklärung von eine Tour von go :

Eine Typzusicherung bietet Zugriff auf den zugrunde liegenden konkreten Wert eines Schnittstellenwerts.

t := i.(T)

Diese Anweisung setzt voraus, dass der Schnittstellenwert i den konkreten Typ enthält T und weist der Variablen t den zugrunde liegenden T-Wert zu.

Wenn ich kein T halte, löst die Anweisung eine Panik aus.

Um zu testen, ob ein Schnittstellenwert einen bestimmten Typ enthält, kann eine Typzusage zwei Werte zurückgeben: den zugrunde liegenden Wert und einen booleschen Wert, der angibt, ob die Zusage erfolgreich war.

t, ok := i.(T)

Wenn ich ein T habe, dann ist t der zugrunde liegende Wert und ok ist wahr.

Wenn nicht, ist ok falsch und t ist der Nullwert vom Typ T, und es tritt keine Panik auf.

HINWEIS: Wert i sollte ein Schnittstellentyp sein.

Fallstricke

Auch wenn i ein Schnittstellentyp ist, ist []i Kein Schnittstellentyp. Um []i In seinen Wertetyp umzuwandeln, müssen wir dies daher einzeln tun:

// var items []i
for _, item := range items {
    value, ok := item.(T)
    dosomethingWith(value)
}

Performance

Die Performance kann langsamer sein als der direkte Zugriff auf den tatsächlichen Wert, wie in diese Stackoverflow-Antwort gezeigt.

20
cizixs
//an easy way:
str := fmt.Sprint(data)
10
Yuanbo