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.