Posts Golang - methods on nil references
Post
Cancel

Golang - methods on nil references

This is the first in a series of posts where I do my best to organize my thoughts around Go: its paradigms and usability as a programming language. I write this as a Java programmer that respects the principles of Elegant Objects.

Go has structs - which are essentially DTOs - and the ability to implement methods on these structs by specifying receivers on functions.

Go allows one to call methods on nil references because, although functions and structs are both equally first-class citizens, functions are more equal than structs (hence this post’s feature image).

What are methods on nil references good for?

Consider this API:

package people

type Person interface {
	Name() string
}

// GetPerson returns nil indicating the person was not found
func GetPerson(name string) Person {
	return nil
}

type person struct {
	name string
}

func (p *person) Name() string {
	return p.name
}	

Our test code will panic if nil is returned by GetPerson():

	person := GetPerson()
	fmt.Print(person.Name()) 	// panic: invalid memory address or nil pointer dereference

There are several ways the API can be improved in order to signal that this person was not found; I’m not sure which one is more idiomatic in Go. Let’s consider implementing the Null Object Pattern by exploiting the fact that you can execute methods on nil references.

Let’s modify the Name() implementation on our person struct:

func (p *person) Name() string {
	if p == nil {
		return "person was not found"
	}
	return p.name
}

Our test code will now print person was not found.

Now Person has a dual nature: depending on circumstances, it can be a normal person with a name, or it can be an “invalid” person. This is an additional cognitive burden when trying to understand this struct. person is now unfocused, breaking the Single Responsibility Principle.

I don’t know what good methods on nil references are for.

This post is licensed under CC BY 4.0 by the author.