39

Why does Go have typed nil? It throws an explicit interface conformation check for convenience. What's the problem of untyped nil and what did the designers want to solve with typed nil?

Rick-777
  • 9,714
  • 5
  • 34
  • 50
eonil
  • 83,476
  • 81
  • 317
  • 516
  • 2
    It might be better if Go used explicitly typed nil like Swift `Optional`. – eonil Jul 26 '15 at 00:56
  • Related, find some reasoning and explanation here: [Hiding nil values, understanding why golang fails here](http://stackoverflow.com/questions/29138591/hiding-nil-values-understanding-why-golang-fails-here) – icza Sep 03 '15 at 05:08

4 Answers4

23

It sounds like you're asking about this error message:

http://play.golang.org/p/h80rmDYCTI

package main

import "fmt"

type A struct {}
type B struct {}

func (a *A) Foo() {
    fmt.Println("A")
}

func (b *B) Foo() {
    fmt.Println("B")
}

func main() {
    n := nil
    n.Foo()
}

This prints:

prog.go:17: use of untyped nil
 [process exited with non-zero status]

In that example, should the program print "A" or "B"?

You have to help the compiler decide. The way you do that is by specifying the type of n.

For example:

http://play.golang.org/p/zMxUFYgxpy

func main() {
    var n *A
    n.Foo()
}

prints "A".

In other languages, n.Foo() might crash immediately if n is nil or its equivalent. Go's language designers decided to let you determine what should happen instead. If you access the pointer without checking for nil, you get the same behavior as in other languages.

Sean
  • 1,785
  • 10
  • 15
  • 3
    Unless the error message you're referring to is "Error communicating with remote server." (which is what I got), you might want to include more information directly in your answer rather than via a link. – Keith Thompson Nov 04 '13 at 04:30
  • 1
    I'd emphasize the point here that calling typed methods on `nil` is both meaningful and useful. – Dustin Nov 05 '13 at 09:26
  • @KeithThompson Good point. I've incorporated the code as well. Dustin, Good point. That's tangential to the question, but worth mentioning in brief. Thanks both of you! – Sean Nov 15 '13 at 23:06
  • For those looking for the syntax: `var SomeNil := SomeType(nil)`. If I later use "SomeNil" to compare to a function (SomeType being a function here), it doesn't work though, claiming "func can only be compared to nil" – Eric Burel Nov 17 '22 at 14:42
19

This is due to type safety. nil is actually the value of uninitialized variables in Go. The nil values for slices, maps, functions, channels, pointers and interfaces are not the same type, and not comparable. See The language spec for more details.

EDIT: As pointed out by @newacct the correct technical term for this is the "zero value" for the type:

When memory is allocated to store a value, either through a declaration or a call of make or new, and no explicit initialization is provided, the memory is given a default initialization. Each element of such a value is set to the zero value for its type: false for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps.

Playground example

There is also some information regarding nil interfaces and errors at Why is my nil error value not equal to nil? in the Go FAQ.

Community
  • 1
  • 1
Intermernet
  • 18,604
  • 4
  • 49
  • 61
  • 3
    "is actually the value of uninitialized variables" Technically, it's called the "zero value" for the type. All types have a zero value. Variables are not uninitialized. – newacct Nov 05 '13 at 02:40
  • @newacct I'm using the terminology found in the language spec (http://golang.org/ref/spec) Where they state "The value of an uninitialized slice is `nil`", "The value of an uninitialized pointer is `nil`" etc. From the same document I can see that you're correct that the "zero value" for all of the types I mentioned in my answer is `nil`. I presume a loose, imprecise definition for "zero value" is "uninitialized" as the Go authors seem happy to use both in the actual spec. I've updated my answer, thanks for the correct terminology. – Intermernet Nov 05 '13 at 05:51
8

All variables in Go need to have a type. Using := operator infers the type from type of right-side expression.

x := [0]int{}       // var x [0]int
y := make(chan int) // var y chan int
z := map[int]int{}  // var z map[int]int
a := func(int) {}   // var a func(int)
b := 42             // var b int
c := 42.0           // var c float64

For pretty much any expression, its type is unambigous, due to needing to explicitly specify the type somewhere - or in case of number literals, having a default when unspecified. The only exception to this rule is nil.

n := nil // var n ???

nil is a valid value for the following.

  • Pointers
  • Unsafe pointers
  • Interfaces
  • Channels
  • Maps
  • Slices
  • Functions

There isn't a good default for a type when an user types nil, so instead Golang rejects this requiring an explicit type specification.

korona
  • 2,308
  • 1
  • 22
  • 37
Konrad Borowski
  • 11,584
  • 3
  • 57
  • 71
6

Without typed-nil, you couldn't use the short assignment statement := with the nil value.

a := nil // Error: use of untyped nil
b := error(nil) // OK

It, likewise, enables the following one-liner:

result, err := "A good result", error(nil)

Writing something like the above may provide some convenience on occasion.


Note, however, that nil is not a keyword or a literal -- and Go does not have a built-in or standard typed-nil value. Typed-nil exists only as the result of one of the following:

  • declaring a nillable typed variable with default ("zero value") initialization
  • assigning nil (directly or indirectly) to a typed value
  • casting the nil identifier to a type (as shown in the examples above).

Here's a clip about subtleties with typed nils and interfaces: GopherCon 2015: Kevin Cantwell - What Could Go Wrong?

Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173