2013-05-30 16 views
9

ich einen int zu einem float64 wie folgt umwandeln:Go Typ Behauptung Umwandlung

var a int = 10 
var b float64 = float64(a) 

Hinsichtlich Behauptungen zu geben, Effective Go heißt es: ‚Der Typ wird durch die Schnittstelle der konkreten Typ gehalten entweder werden müssen oder ein zweiter Schnittstellentyp, in den der Wert konvertiert werden kann. '

Mit dem im Verstand, warum nicht funktioniert wie folgt:

func foo(a interface{}) { 
    fmt.Println(a.(float64)) 
} 

func main() { 
    var a int = 10 
    foo(a) 
} 

Dies ist ein panic: interface conversion: interface is int, not float64 verursacht.

Beachten Sie, dass die Go-Spec sagt:

‚Für einen Ausdruck x von Schnittstellentyp und einen Typ T, der primären Ausdruck

x.(T) 

behauptet, dass x nicht gleich Null ist und dass der Wert gespeichert in x ist vom Typ T.

Das widerspricht der Effective Go-Anweisung, scheint aber mehr im Einklang mit dem, was ich sehe.

Antwort

9

This sentence in Effektive Go scheint in der Tat verwirrend sein. Es sieht so aus, als ob der Autor damals über Strukturen nachgedacht hat.

The chapter on assertions in the specification ist viel klarer.

Für einen Ausdruck x des Schnittstellentyp und einem Typ T, der primäre Ausdruck

x (T) behauptet, daß x nicht gleich Null ist und dass der Wert in x gespeichert ist Typ T. Die Schreibweise x. (T) heißt eine Typassertion.

Genauer gesagt, wenn T nicht ein Interface-Typ ist, x. (T) behauptet, dass der dynamische Typ von x auf den Typ T. In diesem Fall identisch ist, muss T implementieren, um die (Schnittstelle) Art von x ; andernfalls ist die Typbestätigung ungültig, da es für x nicht möglich ist, einen Wert vom Typ T zu speichern. Wenn T ein Schnittstellentyp ist, gibt x. (T) an, dass der dynamische Typ x die Schnittstelle T implementiert.

Die Tatsache you can convert your int to a float (und das Gegenteil) bedeutet überhaupt nicht, dass Sie behaupten können, dass sie vom gleichen Typ sind.

+0

vereinbart, jedoch ist die Operation, wie von der Runtime-Panic-Nachricht vorgeschlagen, tatsächlich eine "Interface-Konvertierung", im Gegensatz zu einer Assertion. Es wäre schön, wenn diese Art von Konversion natürlich passieren könnte. – Ferguzz

+0

Sie können einen Typenschalter machen. Was ist natürlicher für Sie? –

+0

@Ferguzz: Go ist ziemlich explizit in all seinen Konvertierungen, es gibt _no_ implizite oder automatische Konvertierungen. Das ist eine sehr gute Sache. Arten von "natürlichen Umwandlungen" sind das komplette Gegenteil von explizit. – Volker

8

Der Typ muss entweder der konkrete Typ von der Schnittstelle, oder ein zweiter Schnittstelle Typen festzustellen, dass der Wert auf

umgewandelt werden kann erklärt dies im Grunde der following:

package main 

import "fmt" 

type Stringer interface { 
    String() 
} 

type Byter interface { 
    Bytes() 
} 

type Stringbyter interface { 
    Stringer 
    Byter 
} 

type Polymorphic float64 

func (p *Polymorphic) String() {} 

func (p *Polymorphic) Bytes() {} 

func main() { 
    i := interface{}(new(Polymorphic)) 
    if _, ok := i.(Stringer); ok { 
     fmt.Println("i can be asserted to Stringer") 
    } 
    if _, ok := i.(Byter); ok { 
     fmt.Println("i can be asserted to Byter") 
    } 
    if _, ok := i.(Stringbyter); ok { 
     fmt.Println("i can be asserted to Stringbyter") 
    } 
    if _, ok := i.(*Polymorphic); ok { 
     fmt.Println("i can be asserted to *Polymorphic") 
    } 
    if _, ok := i.(int); ok { 
     fmt.Println("i can be asserted to int") // Never runs 
    } 
} 

Die Behauptung zu int schlägt fehl, weil es ein konkreter Typ ist (im Gegensatz zum Schnittstellentyp) wh ich bin nicht *Polymorphic selbst.

0

Sie können nur Assert vom Schnittstellentyp zum zugrunde liegenden Typ eingeben.In diesem Fall int. Dann verwenden Sie die Typkonvertierung von int zu float64