2012-06-13 11 views
5

Ich machte eine einfache Linked List-Schnittstelle, um über Go-Schnittstellen zu lernen, als ich auf diese offensichtliche Inkonsistenz stolperte. nextT ist immer Null, aber der Rückgabewert von next() ist nicht.Inkonsistente Null für Zeiger Empfänger (Go Bug?)

package main 

import (
    "fmt" 
) 

type LinkedList interface { 
    next() LinkedList 
} 

type T struct { 
    nextT *T 
} 

func (t *T) next() LinkedList { 
    //uncomment to see the difference 
    /*if t.nextT == nil { 
     return nil 
    }*/ 
    return t.nextT//this is nil! 
} 

func main() { 
    t := new(T) 
    fmt.Println(t.nextT == nil) 

    var ll LinkedList 
    ll = t 
    fmt.Println(ll.next() == nil)//why isn't this nil? 
} 

Ohne die Null-Prüfung (die ich nicht zu tun haben) in next() bekomme ich

true 
false 

Damit ich das erwartete Ergebnis erhalten

true 
true 

habe ich einen entdeckt Fehler oder ist diese Überraschung aus irgendeinem Grund beabsichtigt? Läuft unter Windows mit Go-Version 1 mit der Zip-Installation (kein MSI)

Antwort

7

Nein, das ist kein Fehler. Eine Schnittstelle in Go ist im Grunde ein Paar von zwei Werten: eine Typinformation und ein Zeiger auf die tatsächlichen Daten. Die Zuordnung des untypisierten Wertes nil zu einer Schnittstelle, die zufällig auch der Nullwert einer Schnittstelle ist, bedeutet, dass die Schnittstelle weder eine Typinformation noch einen Zeiger auf irgendwelche gespeicherten Daten hat.

Wenn Sie dagegen einen *T Zeiger einer Schnittstelle zuweisen, wird die Typinformation entsprechend eingestellt und der Datenzeiger auf diesen Zeiger zeigen. In diesem Fall ist die Schnittstelle nicht mehr nil, weil Sie einen bestimmten Typ mit einem bestimmten Wert darin gespeichert haben. In Ihrem Fall ist es einfach so, dass der von Ihnen gespeicherte Wert Null ist. Sie können eine Typassertion (oder das reflect-Paket) verwenden, um zu überprüfen, ob einer Schnittstelle ein bestimmter Typ zugewiesen ist. Die Typprüfung wird nur erfolgreich sein, wenn die Typinformation übereinstimmt (was offensichtlich niemals der Fall sein kann, wenn Sie vorher nil dieser Schnittstelle zugewiesen haben). Wenn der Test erfolgreich ist, erhalten Sie eine *T zurück, aber dieser Zeiger möglicherweise noch den Wert nil (was ein gültiger Wert für diesen Typ ist).

Werfen Sie einen Blick auf das Paket container/list in der Go-Standardbibliothek, um eine idiomatische allgemeine Verkettungslistenimplementierung anzuzeigen. Es gibt auch eine excellent article von Russ Cox, die eine eingehende Erklärung von Go's Interface-Typ enthält.