The confusion of nil pointer in golang

Ron Liu
2 min readFeb 25, 2023

--

Photo by Kyle Glenn on Unsplash

When I first learned Go, I thought that nil was similar to undefined in JavaScript, and that it represented a lack of value or the absence of an object.

If you think the same way, let’s check the following puzzles.

Can I assign a untyped nil directly to a variable?

nilPointer := nil  // <-- golang compile error: use of untyped nil in assignment

So the answer is NO, you cannot.

Does typed nil equals to untyped nil?

var dogPointer *Dog = nil
fmt.Println("Does (*Dog)nil equal to untyped nil?", dogPointer == nil) // Does (*Dog)nil equal to untyped nil? true

Yes, as you expect.

But does interface{} nil pointing to typed nil equal to untyped nil?

var dogPointer *Dog = nil
pointer = dogPointer
fmt.Println("Dees untyped nil pointing to equal to (*Dog)nil ?", pointer == nil) // Does (*Dog)nil equal to untyped nil? true

Oh, no, that’s wired. Why???

OK, Does interface{} nil equal to untyped nil ?

var pointer interface{} = nil
fmt.Println("Does interface{} nil equal to untyped nil ?", pointer == nil) // Does interface{} nil equal to untyped nil ? true

The answer is Yes, I think it makes sense.

How about other interface assigned as nil equals to untyped nil?

type Animal interface{}
var animal Animal = nil
fmt.Println("Does a normal interface nil equal to untyped nil?", animal == nil) // Does a normal interface nil equal to untyped nil? true

Oh, interface null is actually untyped nil, emm, makes sense.

And that’s why we can use err == nil ?

func call() error {
return nil
}
if call() == nil {
// ...
}

error is a interface, and that's why we can compare with an untyped nil.

Can a typed nil call member function?

type Dog struct{}
func (dog *Dog) Bark() {
fmt.Println("Dog is barking")
}
var dogPointer Dog = nil
dogPointer.Bark() // Dog is barking

The answer is YES, yeah!

What will happen if I want to cast a interface {} nil to a type?

var pointer interface{} = nil
aPointer, ok := pointer.(*Dog)
fmt.Println("Hello", aPointer, ok) // Hello <nil> false

Yeah, it will fail, makes sense

What will happen if I want to cast a typed nil to the type?

pointer = dogPointer
aPointer, ok = pointer.(*Dog)
fmt.Println("Hello", aPointer, ok) // Hello <nil> true

Are you confused ? I am not sure, but I am haha!

--

--

Ron Liu
Ron Liu

No responses yet