2017-04-23 2 views
2

Lassen Sie uns das folgende Programm betrachtenLegendes Typ Behauptungen mit Schnittstellen und Zeiger in Go

type Fruit interface { 
    Color() string 
} 

type Apple struct { 
    color string 
} 

func (x *Apple) Color() string { 
    return x.color 
} 

func (x *Apple) Compare(y Fruit) bool { 
    _, ok := y.(*Apple) 

    if ok { 
     ok = y.Color() == x.Color() 
    } 

    return ok 
} 

func main() { 
    a := Apple{"red"} 
    b := Apple{"green"} 

    a.Compare(&b) 
} 

Nun beachten Sie die letzte Zeile, die a.Compare(&b) sagt. Hier gebe ich einen Zeiger auf Apple. Dies funktioniert korrekt, aber beachten Sie, dass meine Compare Funktion den Zeiger (y Fruit) nicht akzeptiert.

Nun, wenn ich die letzte Zeile ändern a.Compare(b) zu sagen, dann gibt er mir folgende Fehlermeldung:

cannot use b (type Apple) as type Fruit in argument to a.Compare: Apple does not implement Fruit (Color method has pointer receiver)

Was [go] ing hier auf?

+2

Schauen Sie sich diese im Zusammenhang/mögliche doppelte Frage + Antwort: [Go, wird X nicht implementieren Y (... Methode hat einen Zeiger Empfänger)] (http://stackoverflow.com/questions/40823315/go-x-does-not-implement-y-method-has-a-pointer-receiver/40824044#40824044) – icza

Antwort

3

Aus Gründen, die in this answer beschrieben sind, implementiert Apple nicht Fruit, aber *Apple tut. Wenn Sie Color auf Apple (statt *Apple) definieren, wird der Code kompiliert:

package main 

import (
    "fmt" 
) 
type Fruit interface { 
    Color() string 
} 

type Apple struct { 
    color string 
} 

func (x Apple) Color() string { 
    return x.color 
} 

func (x Apple) Compare(y Fruit) bool { 
    _, ok := y.(Apple) 

    if ok { 
     ok = y.Color() == x.Color() 
    } 

    return ok 
} 

func main() { 
    a := Apple{"red"} 
    b := Apple{"green"} 

    fmt.Println(a.Compare(b)) 
} 
+0

In Ordnung, jetzt verstehe ich den Unterschied zwischen Zeiger und Wertempfänger. Eine Frage also. Warum funktioniert 'a.Compare (& b)'? Ich definiere einen Zeigerempfänger, aber 'a: = Apple {" red "}' macht 'a' einen Wert, keinen Zeiger. Warum kompiliert 'a.Compare (& b)'? – treecoder

+0

Von https://golang.org/doc/effective_go.html#methods: "Die Regel über Zeiger vs. Werte für Empfänger ist, dass Wert Methoden auf Zeiger und Werte aufgerufen werden können, aber Zeiger Methoden können nur auf Zeigern aufgerufen werden. " gefolgt von einigen Worten, warum die Sprache so gestaltet wurde – fuglede