Skip to main content
ertius.org

go semantics can be fiddly

I've been writing a bunch of Go lately. It's generally nice since the compiler or my editor-run-linters whinge at me early on before the code does something but, but not always...

I'd made a change that caused the name err to not be first used so early in a long setup function, so I changed this line:

db, err = sql.Open("postgres", dbURL)

to look like this:

db, err := sql.Open("postgres", dbURL)

thus causing err to be defined here and fixing the complaint about err. Unfortunately, it also created a local shadowing of db, which is a global DB handle, which caused it now to not be initialised in a distant function that then panic'd with a

runtime error: invalid memory address or nil pointer dereference

In retrospect, it's fairly clear when reading the traceback what wasn't initialised, but it's also harder to spot in practice, since I was explicitly setting db, and I'd made a bunch of other seemingly innocuous code changes at the same time. Luckily I found this where some other poor sod had done the same thing.

Interestingly, I'm using lots of linters for this project, and none of them complained about a pretty clear-to-the-computer uninitialised variable being used.