Right, let’s talk about go test flags. This is where you stop just running tests and start interrogating them. The default go test is polite; it runs your tests and tells you if they passed. These flags are how you get it to spill its guts, confess its secrets, and do a little performance art for you. We’ll focus on the ones you’ll use daily.

The -run flag is your first line of defense against running your entire 5,000-test suite when you just tweaked one function. It takes a regular expression and only runs tests whose names match it. Simple, right? The devil is in the details.

Let’s say you have a test file for a Calculator type:

func TestAdd(t *testing.T) { ... }
func TestSubtract(t *testing.T) { ... }
func TestAdd_WithNegativeNumbers(t *testing.T) { ... }
func TestMultiply(t *testing.T) { ... }

Running go test -run Add will run both TestAdd and TestAdd_WithNegativeNumbers. This is because the regex Add matches any test name containing “Add”. To be more precise, you can anchor it: go test -run '^TestAdd$' will only run the exact TestAdd test. The quotes are for your shell’s benefit, so it doesn’t try to expand the $ itself.

Pro Tip: This is also how you run your subtests individually. If you have a table-driven test with subtests named TestAdd/positive_case and TestAdd/negative_case, you can run just the negative ones with -run 'TestAdd/negative_case'. This is a lifesaver for debugging a single failing case in a table of 100.

The -bench Flag: Where We Stop Guessing and Start Measuring

The -bench flag is for running benchmarks. It uses the same regex syntax as -run. By default, go test doesn’t run benchmarks, which is sensible. To run them all, use -bench=.. The . is a regex that matches everything. To run just your BenchmarkAdd function, use -bench=Add.

But here’s the thing the docs don’t scream at you: -bench runs after your tests. If your tests fail, your benchmarks won’t run. This is Go’s way of saying, “Why are you benchmarking broken code, you maniac?” It’s a good feature.

The output tells you how many times the loop ran (1000000000) and how many nanoseconds per operation (1.87 ns/op). The benchmark runtime adjusts the loop count (b.N) until it can get a stable measurement. Your job is to make sure the code inside the loop is what you actually want to measure.

The -count Flag: For When You Suspect Gremlins

Ever had a test that fails sometimes? A classic heisenbug? -count is your new best friend. It simply runs your tests or benchmarks n times in sequence.

go test -count 10 runs your entire test suite ten times. If a test fails intermittently, this will often smoke it out. For benchmarks, this is even more crucial. A single benchmark run can be noisy due to your OS deciding to update something in the background. Running a benchmark multiple times (e.g., -bench=. -count 5) gives you a much better idea of its true performance characteristics. You’ll see multiple results, and you can mentally (or with tools) average them or find the median.

The -race Flag: The Most Important Flag You Aren’t Using Enough

If you are writing concurrent code and you are not using -race, you are not testing your code. You are hoping. The race detector is a world-class piece of engineering that instruments your code to find data races—those horrifying bugs where two goroutines access the same memory without synchronization and one of the accesses is a write.

Run your tests with -race always. Put it in your CI. The performance hit is significant, but it’s a million times cheaper than debugging a race condition in production. It’s so good it feels like cheating. I’ll wait while you go add -race to your Makefile.

The -cover Flag: The Code Coverage Report Card

Code coverage is a seductive metric. It tells you what percentage of your code was executed during the tests. It does not tell you if your tests are any good. You can have 100% coverage and still have utterly useless tests that don’t assert anything correctly.

That said, it’s an incredibly useful tool for finding completely untested corners of your code. Run go test -cover. You’ll get a single percentage. The more useful mode is -coverprofile to generate a file and then use go tool cover to visualize it.

go test -coverprofile=coverage.out
go tool cover -html=coverage.out

This opens a browser window showing your code, with tested lines in green and untested ones in red. It’s the fastest way to find the code you forgot to write tests for. Use it to find blind spots, not to boast in a PR. Aim for high coverage, but worship good design, not a number.