nil functions

December 18, 2023

Calls

Calling a nil function value causes a run-time panic.

So, calling a nil function causes a panic. Sensible enough. But when would you ever run across a nil function?

Let’s look at some examples.

This is probably the most obvious example, and perhaps one that popped to your mind:

var fn func(int) // fn is of type func(int), but uninitialized, so nil

fn(3) // run-time panic

But let’s consider another example, which can be a bit more confusing.

type Fooer interface {
	Foo()
}

type Wrapper struct {
	Fooer
}

w := &Wrapper{}
f := w.Foo
f() // run-time panic

Okay, that’s a lot of set-up for a run-time panic on a nil function. What’s actually going on?

Well first, I created an interface called Fooer, then I embedded that interface in a struct called Wrapper. This can be a useful technique in some cases, but it assumes that you’ll be setting the Fooer field of the struct to something that implements the interface. In contract, when I defined w := &Wrapper{}, I did not set the Fooer field, so it gets a nil value.

Then if I call w.Foo(), or set function variable to its value (i.e. f := w.Foo), I end up with a nil method or function respectively, and thus a run-time panic.

Quotes from The Go Programming Language Specification Version of August 2, 2023


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Refresher on methods

In yesterday’s email, I failed to include the example included in the spec, which doesn’t make sense to include otherwise. I’ve updated the web version of the email in case you’re super curious to see what I left out. We’ve already covered these details, but they’re logically mentioned again in the section about function calls, so we’ll cover them here: Calls … A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m.


Special case: Multi-value arguments to functions

You may recall that when we started the section on function calls, we were told about a “special case”… well here it is! Calls … As a special case, if the return values of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order.


Evaluation of function parameters

Calls If f denotes a generic function, it must be instantiated before it can be called or used as a function value. We’ve seen this rule applied to methods and other types. It should be standard by now, so I won’t dwell on it. In a function call, the function value and arguments are evaluated in the usual order. After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution.