2012-06-13 14 views
5

Stavo facendo una semplice interfaccia elenco collegato per conoscere le interfacce Go quando sono incappato in questa apparente incoerenza. nextT è sempre nullo ma il valore restituito di next() non lo è.Incoerente nil per ricevitore puntatore (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? 
} 

Senza il controllo nullo (che non avrei dovuto fare) in next() ottengo

true 
false 

Con esso ottengo il risultato atteso

true 
true 

Avere ho scoperto un bug o è questa sorpresa intenzionale per qualche motivo? Esecuzione su Windows con Go versione 1 utilizzando l'installazione zip (senza MSI)

risposta

7

No, non è un bug. Un'interfaccia in Go, è fondamentalmente una coppia di due valori: un tipo di informazione e un puntatore ai dati reali. Assegnare il valore non codificato nil a un'interfaccia, che è anche il valore zero di un'interfaccia, significa che l'interfaccia non ha né informazioni di tipo né puntatori ai dati memorizzati.

D'altra parte, l'assegnazione di un puntatore *T a un'interfaccia, imposterà le informazioni sul tipo di conseguenza e consentirà al puntatore di dati di puntare a questo puntatore. In tal caso, l'interfaccia non è più nil, perché è stato memorizzato un tipo specifico con un valore specifico all'interno. Nel tuo caso succede solo che il valore che hai memorizzato è nullo. È possibile utilizzare un'asserzione di tipo (o il pacchetto reflect) per verificare se a un'interfaccia è stato assegnato un tipo specifico. L'asserzione di tipo avrà successo solo se le informazioni sul tipo corrispondono (il che ovviamente non può mai essere il caso se prima hai assegnato zero a quell'interfaccia). Se il test ha esito positivo, verrà restituito uno *T, ma questo puntatore potrebbe avere ancora il valore nil (che è un valore valido per quel tipo).

Dai un'occhiata al pacchetto container/list nella libreria standard Go per vedere un'implementazione di elenchi di collegamenti generali più idiomatici. C'è anche un excellent article di Russ Cox che contiene una spiegazione approfondita del tipo di interfaccia di Go.

Problemi correlati