Go Methods on Values and Pointers

TLDR: I was surprised by the behavior of a method on a value. Should have used a method on a pointer instead.

This story starts when I was attempting to put together a simple web application using go. I was following the, what I believe to be good, recommendation of Alex Edwards on Organizing Database Access and was using dependency injection to provide some initialized resources to all my request handlers.

Things looked kind of like:

// my Environment with application level resources
type controller struct {
    router *mux.Router
    db     *store
}

// an example handler that would then use those resource by way of registering
// as a route
func (c controller) Home(w http.ResponseWriter, r *http.Request) {

I had used this approach previously with good results but this time it wasn't working the way I expected things to. Specifically when I attempted to use a resource from the controller I was getting:

2018/10/07 11:31:59 runtime error: invalid memory address or nil pointer dereference

As I dug into it I realized that the ordering of things mattered. For example the handler could “see” items that were defined prior to registering it, but ones after it was registered were nil. This was entirely unexpected.

This was ok:

func newController(config *config) controller {
    c := controller{}                   // 1. create controller
    c.db = newDatastore(config.DBPath)  // 2. connect to database
    c.router = mux.NewRouter()          // 3. create router and register handlers
    c.registerRoutes()
...

This was not:

func newController(config *config) controller {
    c := controller{}                   // 1. create controller
    c.router = mux.NewRouter()          // 2. create router and register handlers
    c.registerRoutes()
    c.db = newDatastore(config.DBPath)  // 3. connect to database
...

At first I simply made that ordering change and moved on but it struck me as odd. So with a night of rest I decided to look back into it. Relatively quickly searching this search progression “golang func on a struct” -> “golang struct methods” -> lead me to Don't Get Bitten by Pointer vs Non-Pointer Method Receivers in Golang and the Go FAQs Should I define methods on values or pointers?

Between these two I was finally on to something. First off I learned the proper terminology of a “methods receiver” and furthermore about the distinction between methods on pointers and methods on values. To use the example from the Golang Docs:

func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct)  valueMethod()   { } // method on value

With this knowledge I mocked up a simplified example in the Go Playground and confirmed both the behavior I was seeing as well as the fix. Use methods on pointers like so:

// method on pointer not method on value like before
func (c *controller) Home(w http.ResponseWriter, r *http.Request) {

One thing that perhaps should have been clear but even after reading those articles was still a bit surprising was that my registered “value method” was receiving the value of the struct at the time it was declared.

My understanding still is far from complete. Specifically I am not 100% sure about the interaction between this pointer/value distinction and the storing of the function (what I call “registering the handler” above). However I definitely learned something.

Perhaps it's a bit naive but my new default is to just use methods on pointers. There seems little reason not to.

I certainly welcome any thoughts, feedback, clarifications, corrections on this. Contact info on the about page.

P.S. When I went back to find the Organizing Database Access article I more clearly groked what it meant by dependency injection and it triggered some recall of other articles along the lines of “Dependency injection will eat your homework”. I'm not sure if those are right. Honestly I kind of like the pattern I've been using, but perhaps this is a sharp corners to be aware of.

go