In a Go package, an Example function prints the wrong text yet go test passes. Why?
answer
- a check that never ran always passes
- no output block, no execution
- the block must be the last comment
- -v lists what actually ran
basics
~20 sAlmost certainly the example is never executed. An example runs only if the last comment in its body starts with // Output:, and only if the character after Example is upper-case; otherwise it is compiled, skipped and silently passes.
solid answer
~40 sExamples fail open, not closed. Three things silently disable one: no `// Output:` block at all; an output block that is no longer the last comment in the body, because someone appended a note under it; or a name the tooling does not recognise as an example, such as `Examplecanonical` with a lower-case letter after the prefix. In each case the function is still compiled — so it survives review looking like a test — but never called. Confirm it with `go test -run Example -v` and read which example names actually appear in the run listing; anything missing was skipped. `go vet` catches the naming and signature variants. The durable fix is to require both in the build, since the failure mode here is silence rather than a red test.
code
text · 5 lines$ go test -run Example -v ./...
=== RUN ExampleCanonical
--- PASS: ExampleCanonical (0.00s)
PASS
ok example.com/urlutil 0.004sgo deeper
Remember the shape of the trap: an example with no // Output: comment is compiled but never run, so it can print anything. Know that go test -run Example -v lists the ones that really executed.
Explain all three silent causes — no output block, an output block that is no longer the last comment, and a name with a lower-case letter after Example — and which of them go vet reports.
Show how you would confirm it in a real package under time pressure: read the verbose run listing, break an expected line to prove the check is live, and put go vet in the pipeline so the naming faults stop reaching review.
Own the standard that keeps published documentation honest. Decide whether unverified examples may ship, what the build enforces automatically, and how a team distinguishes a deliberately unchecked example from a forgotten one.
## The failure mode: a check that fails open Most test failures announce themselves. This one does the opposite. An example that is not run cannot fail, so a package can carry a set of examples that look like verification, render on the documentation page as if they were authoritative, and check nothing at all. For a library other teams read before they read your code, that is worse than having no examples: the documentation now asserts behaviour that nothing enforces. ## The three ways it happens **1. There is no output block.** The example prints, the runner has nothing to compare against, and the function is skipped. This is the common case and it is easy to create by accident: you write the example first to see what it prints, intend to paste the output in, and never do. **2. The output block is no longer last.** The tooling looks at the *last* comment in the function body. A later edit that adds a trailing note — `// TODO: cover the empty case` under the output block — moves the output block out of that position, and the example goes quiet. Nothing about the diff looks dangerous, which is exactly why this survives review. ```go func ExampleCanonical() { fmt.Println(Canonical("https://example.com/p?b=2&a=1")) // Output: https://example.com/p?a=1&b=2 // TODO: also cover an empty query } ``` **3. The name is not recognised.** The character after `Example` must not be lower-case, so `Examplecanonical` is an ordinary function that nothing calls. A misspelt symbol name — `ExampleCanonicl` after a rename — still runs if it has an output block, but it attaches to no symbol, so it disappears from the documentation page while quietly continuing to pass. ## Diagnosing it The fastest confirmation is the verbose run listing: ``` $ go test -run Example -v ./... === RUN ExampleCanonical --- PASS: ExampleCanonical (0.00s) PASS ``` The listing names every example that actually executed. An example you can see in the source but not in that output was skipped, and you now know which of the three causes to look for. Note that `-run` accepts a regular expression matched against test, example and fuzz-target names, which is why `-run Example` is a convenient filter here. A second, blunter check: temporarily break the example's expected output — change one character in the `// Output:` block — and re-run. If the package still passes, the example is definitively not running. This is worth doing once on any example you are about to rely on. `go vet` covers the name-shaped causes. Its test checks report an example whose name has a lower-case letter after the prefix, one whose signature is not niladic, one with a malformed suffix, and — for an example written against the package's exported surface from its external test package — one whose name refers to an identifier that does not exist. It does not report a missing output block, because an example without one is legitimate: it is still a compile check on the documentation, and for output that cannot be made deterministic it is the only honest choice. ## Keeping it fixed The defect is structural, so the fix is structural rather than a matter of care: - Run `go vet` in the build, not by hand. It is the only automated catch for the naming variants. - When reviewing an example, look at where the output block sits, not just that one exists. "Last comment in the body" is the actual rule and it is invisible unless you are looking for it. - Treat an example with no output block as a deliberate, commented decision — say in the body why the output cannot be checked. An unexplained one is indistinguishable from a forgotten one. - Prefer several small suffixed examples over one that prints many lines. A long output block drifts one line at a time and is re-pasted wholesale when it breaks, which is how a stale expectation gets blessed. - When an example's expected output does change, read the diff of the output block as carefully as a diff of the code. It is the specification. ## Why the design accepts this The alternative — refusing to build an example without an output block — would forbid the legitimate case where a function's result cannot be printed deterministically but the calling code is still worth showing. Go chose to keep the compile-only example useful and accept that the check is opt-in. Once you know the check is opt-in, the review habit follows: assume an example is not verifying anything until you have seen its name in a `-v` run.
- Would go vet have caught an example that is missing its // Output: comment?No, and deliberately so. An example without an output block is legitimate — it is still a compile check on the documentation, and it is the right choice when the result cannot be printed deterministically. `go vet` catches the name and signature faults instead: a lower-case letter after `Example`, a non-niladic signature, a malformed suffix, a name pointing at an identifier that does not exist.
- How would you prove to a reviewer that a given example really is being checked?Run `go test -run Example -v` and point at the example's name in the output; only executed examples are listed. As a stronger demonstration, change one character in the expected output and show the package failing. If it still passes, the example was never running.
- What review habit stops this recurring in a package other teams depend on?Read the output block's position, not just its presence — the rule is that it must be the last comment in the body, so a trailing note silently disables it. Keep `go vet` in the build for the naming faults, and require any example that deliberately has no output block to say why in a comment, so a forgotten one is distinguishable from an intentional one.
saying these in an interview costs you the question
- Assuming a passing package means every example ran
- Adding a note under the // Output: block without noticing
- Expecting go vet to catch a missing output block
- Blaming the test cache for an example that never fails
- Trusting a rendered documentation example as verified behaviour