ist, weil eine Variable statischen Typ Nexter
(die nur eine Schnittstelle ist) kann Werte von vielen verschiedenen Typen dynamischen halten.
Ja, da *Node
Nexter
implementiert, Ihre p
Variable Typ einen Wert von möglicherweise *Node
, halten, aber es kann andere Arten als auch die Nexter
implementieren halten; oder es kann nichts überhaupt halten (nil
Wert). Und Type assertion kann hier nicht verwendet werden, da aus der spec zitieren:
x.(T)
asserts that x
is not nil
and that the value stored in x
is of type T
.
Aber x
in Ihrem Fall ist nil
. Und wenn die Typassertion falsch ist, tritt eine Laufzeitpanik auf.
Wenn Sie Ihr Programm ändern Ihre p
Variable zu initialisieren:
var p Nexter = (*Node)(nil)
Ihr Programm ausgeführt wird, und geben Behauptung erfolgreich ist. Dies liegt daran, dass ein Schnittstellenwert tatsächlich ein Paar in der folgenden Form enthält: (value, dynamic type)
, und in diesem Fall wird p
nicht nil
sein, sondern ein Paar (nil, *Node)
; Details siehe The Laws of Reflection #The representation of an interface.
Wenn Sie auch nil
Werte von Schnittstellentypen zu handhaben möchten, können Sie es so explizit überprüfen:
if p != nil {
n = p.(*Node) // will not fail IF p really contains a value of type *Node
}
Oder besser: Verwenden Sie die spezielle "Komma-ok" Form:
// This will never fail:
if n, ok := p.(*Node); ok {
fmt.Printf("n=%#v\n", n)
}
Verwendung des "Komma-OK" -Formulars:
The value of ok
is true
if the assertion holds. Otherwise it is false
and the value of n
is the zero value for type T
. No run-time panic occurs in this case.