*Updated Sun, Jan 8, 2023: Updated install instructions to use golangci-lint instead of gometalinter.

I just created gochecknoglobals and gochecknoinits. The lint tools scan Go code in the current directory and error if they discover global variables or package-level init functions.

I recently saw Dave Cheney’s tweet about not using global variables and read Peter Bourgon’s in-depth follow up A theory of modern Go. The tl;dr is magic code is bad because you need to know more about how it works than is immediate obvious from reading about it’s use, and global variables and init functions are magic because they carry side-effects through an application that aren’t contained by the functions that use or rely on them.

In my experience this tends to be true. Even in small apps I have worked on global variables have resulted in code that is harder to understand, and when I import a package that has an init function it surprises me.

This has led me to avoid using globals and init whenever I can. As an example both gochecknoglobals contained gochecknoinits use no globals or inits.

Install:

go install 4d63.com/gochecknoglobals@latest
go install 4d63.com/gochecknoinit@latest

Usage:

gochecknoglobals
gochecknoinits

Usage with golangci-lint:

golangci-lint run --enable gochecknoglobals,gochecknoinits

Source: