6

I was doing a simple linked list interface to learn about Go interfaces when I stumbled upon this apparent inconsistency. nextT is always nil but the return value of next() isn't.

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?
}

Without the nil check (which I shouldn't have to do) in next() I get

true
false

With it I get the expected result

true
true

Have I discovered a bug or is this surprise intentional for some reason? Running on Windows with Go version 1 using the zip installation (no MSI)

1 Answer 1

8

No, that's not a bug. An interface in Go, is basically a pair of two values: a type information and a pointer to the actual data. Assigning the untyped value nil to an interface, which also happens to be the zero value of an interface, means that the interface has neither a type information nor a pointer to any data stored.

On the other hand, assigning a *T pointer to an interface, will set the type information accordingly and let the data pointer point to this pointer. In that case, the interface isn't nil anymore, because you have stored a specific type with a specific value inside. In your case it just happens that the value you have stored is nil. You can use a type assertion (or the reflect package) to check if an interface has specific type assigned. The type assertion will only succeed if the type information matches (which can be obviously never be the case if you have assigned nil to that interface before). If the test succeeds, you will get a *T back, but this pointer might still have the value nil (which is a valid value for that type).

Take a look at the container/list package in the Go standard library to see a more idiomatic general linked-list implementation. There is also an excellent article by Russ Cox that contains an in-depth explanation of Go's interface type.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.