Sie können auf den Artikel " Verwendung von Schnittstellen in Go " verweisen (basierend auf " Russ Cox 'Beschreibung der Schnittstellen "):
Was ist eine Schnittstelle?
Eine Schnittstelle besteht aus zwei Dingen:
- es ist eine Reihe von Methoden,
- es ist aber auch ein typ
Der interface{}
Typ, die leere Schnittstelle, ist die Schnittstelle, die keine Methoden hat.
Da es kein Schlüsselwort implementiert gibt, implementieren alle Typen mindestens null Methoden, und die Erfüllung einer Schnittstelle erfolgt automatisch. Alle Typen erfüllen die leere Schnittstelle .
Das heißt, wenn Sie eine Funktion schreiben, die einen interface{}
Wert als Parameter verwendet, können Sie diese Funktion mit einem beliebigen Wert versehen .
(Das ist, was Msg
in Ihrer Frage darstellt: jeder Wert)
func DoSomething(v interface{}) {
// ...
}
Hier wird es verwirrend:
Was ist der Typ innerhalb der DoSomething
Funktion ?v
Anfänger glauben, dass „ v
von jeder Art ist“, aber das ist falsch.
v
ist von keiner Art; es ist vom interface{}
Typ .
Wenn Sie einen Wert an die DoSomething
Funktion übergeben, führt die Go-Laufzeit (falls erforderlich) eine Typkonvertierung durch und konvertiert den Wert in einen interface{}
Wert .
Alle Werte haben zur Laufzeit genau einen Typ und v
der eine statische Typ interface{}
.
Ein Schnittstellenwert besteht aus zwei Datenwörtern :
- Ein Wort wird verwendet, um auf eine Methodentabelle für den zugrunde liegenden Typ des Werts zu verweisen.
- und das andere Wort wird verwendet, um auf die tatsächlichen Daten zu verweisen, die von diesem Wert gehalten werden.
Nachtrag: Hier ist Russ 'Artikel bezüglich einer Schnittstellenstruktur ziemlich vollständig:
type Stringer interface {
String() string
}
Schnittstellenwerte werden als Zwei-Wort-Paar dargestellt, das einen Zeiger auf Informationen über den in der Schnittstelle gespeicherten Typ und einen Zeiger auf die zugehörigen Daten gibt.
Durch Zuweisen von b zu einem Schnittstellenwert vom Typ Stringer werden beide Wörter des Schnittstellenwerts festgelegt.
Das erste Wort im Schnittstellenwert zeigt auf das, was ich als Schnittstellentabelle oder itable bezeichne (ausgesprochen i-table; in den Laufzeitquellen lautet der Name der C-Implementierung Itab).
Die itable beginnt mit einigen Metadaten zu den beteiligten Typen und wird dann zu einer Liste von Funktionszeigern.
Beachten Sie, dass die itable dem Schnittstellentyp entspricht, nicht dem dynamischen Typ .
In unserem Beispiel Stringer
listet die itable für das Halten von Typ Binary die Methoden auf, die verwendet werden, um Stringer zu erfüllen. Dies ist nur String
: Die anderen Methoden ( Get
) von Binary erscheinen nicht in der itable
.
Das zweite Wort im Schnittstellenwert zeigt auf die tatsächlichen Daten , in diesem Fall eine Kopie von b
.
Die Zuweisung erstellt var s Stringer = b
eine Kopie von b
und zeigt nicht auf b
denselben Grund, var c uint64 = b
aus dem eine Kopie erstellt wird: Wenn sich b
später etwas ändert s
und c
der ursprüngliche Wert haben soll, nicht der neue.
In Schnittstellen gespeicherte Werte können beliebig groß sein, aber nur ein Wort ist für das Halten des Werts in der Schnittstellenstruktur vorgesehen, sodass die Zuweisung einen Speicherblock auf dem Heap zuweist und den Zeiger im Ein-Wort-Slot aufzeichnet.
interface{}
ist mehr oder weniger das Äquivalent vonvoid *
in C. Es kann auf alles verweisen und Sie benötigen eine Cast / Type-Zusicherung, um es zu verwenden.