Go Tooling

beginner go testing tooling

One of the best things about Go is that the tooling is built in. Compiler, test runner, formatter, doc viewer, dependency manager — all one go command. No webpack, no Babel, no debates about which formatter to use.

In simple language: in most languages we bolt on a dozen separate tools; in Go they come in the box.

The everyday commands

go run main.go     # compile + run in one step (great for scripts/dev)
go build           # compile to a binary, no run
go test ./...      # run all tests recursively
go install         # build and drop the binary in $GOPATH/bin

go build produces a single static binary with no runtime dependencies — we copy that one file to a server and it just runs. That’s why Go is so popular for containers and CLIs.

Formatting — there’s only one true format

gofmt (and its wrapper go fmt) formats our code into the one canonical Go style. Tabs, spacing, alignment — all decided for us. There are no style debates in Go because there’s literally one accepted format.

go fmt ./...   # format all files in the module
gofmt -d file.go   # show what WOULD change (diff), don't write

Most teams run gofmt on save. goimports is the popular upgrade — it does everything gofmt does plus automatically adds and removes import statements for us.

goimports -w main.go   # format AND fix imports, write in place

go vet — catch suspicious code

go vet is a built-in static checker. It doesn’t check style (that’s gofmt’s job) — it flags likely bugs: a Printf with the wrong number of arguments, an unreachable line, a struct tag typo, a lock copied by value.

go vet ./...   # report suspicious constructs

Think of it as a free, fast first-pass bug catcher. It runs automatically as part of go test, too.

Managing dependencies

Dependencies are handled by Go modules. The two commands we lean on:

go get github.com/some/pkg   # add or upgrade a dependency
go mod tidy                  # add missing deps + remove unused ones

go mod tidy is the housekeeper — after we add or delete imports, it syncs go.mod and go.sum so they exactly match what the code actually uses. Run it before committing.

Reading docs and generating code

go doc fmt.Println        # print docs for a function, right in the terminal
go doc -all strings       # full docs for a whole package
go generate ./...          # run //go:generate directives in the code

go doc reads the doc comments straight from source — no internet needed. go generate runs commands we’ve annotated in comments (//go:generate ...), commonly used to produce mocks or stringer methods. It’s not automatic; we run it ourselves.

The standard tools cover a lot, but two community linters go further:

  • staticcheck — a deep static analyzer that catches many subtle bugs and dead code go vet misses.
  • golangci-lint — a fast meta-linter that bundles staticcheck, go vet, and dozens of others behind one config. This is the de-facto CI standard in most Go shops.
golangci-lint run ./...   # run the whole linter bundle

These aren’t built in, but every serious team installs golangci-lint. Worth name-dropping in an interview.

Interview soundbite

Go’s toolchain is built in — one go command does build, run, test, fmt, vet, doc, and module management, and go build spits out a single static binary. gofmt enforces one canonical format so there are no style arguments, goimports also fixes imports, go vet catches likely bugs, and go mod tidy syncs dependencies. The popular third-party linters are staticcheck and golangci-lint, the CI standard.