2012-06-13 8 views
5

Robiłem prosty interfejs listy linków, aby poznać interfejsy Go, gdy natknąłem się na tę pozorną niespójność. nextT jest zawsze zerowe, ale wartość zwracana next() nie jest.Niespójne zero dla odbiornika pointeru (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? 
} 

Bez nil czeku (czego nie powinno się robić) w next() uzyskać

true 
false 

Dzięki niemu uzyskać oczekiwany rezultat

true 
true 

Czyżbym odkrył czy jest to z jakiegoś powodu celowa niespodzianka? Uruchamianie w systemie Windows z wersją Go 1 przy użyciu instalacji zip (bez MSI)

Odpowiedz

7

Nie, to nie jest błąd. Interfejs w Go to po prostu para dwóch wartości: informacja o typie i wskaźnik do rzeczywistych danych. Przypisanie niezaszyfrowanej wartości nil do interfejsu, który również jest zerową wartością interfejsu, oznacza, że ​​interfejs nie zawiera informacji o typie ani wskaźnika do przechowywanych danych.

Z drugiej strony przypisanie do interfejsu wskaźnika *T spowoduje odpowiednie ustawienie informacji o typie i pozwoli wskaźnikowi danych wskazać ten wskaźnik. W takim przypadku interfejs nie jest już nil, ponieważ został zapisany określony typ o określonej wartości wewnątrz. W twoim przypadku dzieje się tak, że wartość, którą zapisałeś, jest zerowa. Możesz użyć asercji typu (lub pakietu reflect), aby sprawdzić, czy interfejs ma przypisany określony typ. Asercja typu zakończy się sukcesem tylko wtedy, gdy informacje o typie będą zgodne (co oczywiście nigdy nie będzie możliwe, jeśli wcześniej przypisałeś zero do tego interfejsu). Jeśli test się powiedzie, otrzymasz z powrotem *T, ale ten wskaźnik może nadal mieć wartość nil (która jest poprawną wartością dla tego typu).

Zapoznaj się z pakietem container/list w standardowej bibliotece Go, aby wyświetlić bardziej idiomatyczną ogólną implementację listy połączonych list. Istnieje również wersja excellent article autorstwa Russa Coxa, która zawiera szczegółowe wyjaśnienie typu interfejsu Go.