---
title: Go Typed Nil
date: 2024-06-12
description: Why an interface holding a nil pointer is not itself nil in Go, and how typed nils can cause unexpected behavior.
tags: [go]
---

The following code doesn't do what you might expect:

```go
package main

import "fmt"

func main() {
    var i *impl

    fmt.Println("i == nil:", i == nil)
    what(i)
}

type impl struct{}

func (i *impl) do() {}

func what(i interface{ do() }) {
    fmt.Println("i == nil:", i == nil)
}
```

If you expected the `what` function to print `i == nil: true`, then keep
reading...

## Typed Nils

The behavior observed is due to the way interfaces and nil values interact in
Go. To understand why the `what` function is able to see the `i` argument as
non-nil, we need to dig into the details of how Go handles interface values.

1. Interface Values: In Go, an interface value is a tuple of a type and a value.
   An interface value is `nil` only if both the type and the value are `nil`.
1. Concrete vs Interface nil: When you assign a concrete type value (which
   happens to be `nil`) to an interface, the interface itself is not `nil`. This
   is because the interface value now contains a type (the concrete type) and a
   value (`nil`).

## Explanation

1. Declaring `var i *impl` initializes it to `nil`.
   - `i` is a pointer to `impl` and is initialized to `nil`.
1. Printing `i == nil` in `main` is `true`
   - because `i` is a `nil` pointer to `impl`
1. Calling `what(i)` function:
   - the function `what` takes an argument of type `interface{ do() }`
1. Inside `what` function:
   - `i` (which is `nil`) is passed to `what`
   - it is assigned to the parameter `i` of type `interface{ do() }`
1. Interface value construction:\
   The value of `i` inside `what` is now an interface that holds:
   - Type: `*impl` (the concrete type of the value passed in)
   - Value: `nil` (the value of the concrete type)
1. Checking `i == nil` prints `false` because the interface `i` is not `nil`:
   - The type part of the interface is `*impl`.
   - The value part of the interface is `nil`.

## Summary

The `what` function sees the `i` argument as non-nil because, in Go, an
interface holding a `nil` pointer is not itself `nil`. The interface contains
type information (`*impl`) and a `nil` value. Therefore, when the code checks if
`i` is `nil`, it returns `false` since the type information (`*impl`) is
present.

## Reference material

- [Go FAQ][1]
- [Dave Cheney][2]

[1]: https://go.dev/doc/faq#nil_error
[2]: https://dave.cheney.net/2017/08/09/typed-nils-in-go-2
