Skip to content

/google-go-style

Use when writing, reviewing, or refactoring Go code; when handling errors (fmt.Errorf, %w, sentinel, errors.Is, errors.As); when deciding between panic, error return, and log.Fatal; when writing tests (table-driven, t.Helper, t.Fatal vs t.Error, goroutines); when designing API

shell
$ npx -y skills add cicdteam/google-go-style --skill google-go-style --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/google-go-style
How auto-invocation works

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when writing, reviewing, or refactoring Go code; when handling errors (fmt.Errorf, %w, sentinel, errors.Is, errors.As); when deciding between panic, error return, and log.Fatal; when writing tests (table-driven, t.Helper, t.Fatal vs t.Error, goroutines); when designing API

SKILL.md

google-go-style.SKILL.md
name: google-go-style
description: Use when writing, reviewing, or refactoring Go code; when handling errors (fmt.Errorf, %w, sentinel, errors.Is, errors.As); when deciding between panic, error return, and log.Fatal; when writing tests (table-driven, t.Helper, t.Fatal vs t.Error, goroutines); when designing API surface (option struct, variadic options, channel direction, context); when naming functions, methods, packages, receivers, or test doubles; when laying out packages and imports; when initializing variables or building strings.

Google Go Style — Skill

_Derived from the [Google Go Style Guide](https://google.github.io/styleguide/go/), © Google LLC, licensed [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/). This skill is a derivative digest, not a verbatim reproduction._

Codifies the [Google Go Style Guide](https://google.github.io/styleguide/go) (canonical + normative + best-practices) into actionable rules.

The full guide is large. This file holds only what should be in your head **on every Go change**. For deeper rules, load the matching `references/*.md`. For unusual situations, WebFetch the source — the guide is normative.

Quick Rules

Apply on every line of Go you write or review.

Naming

  • **No `Get` prefix on getters.** `User()`, not `GetUser()`. Exception: the underlying concept *is* "get" (HTTP GET).
  • **Don't repeat the package name** in identifiers. `bytes.Buffer`, not `bytes.BytesBuffer`. `widget.New`, not `widget.NewWidget`.
  • **Receiver names: 1–2 letters, abbreviation of the type, consistent across all methods.** Never `this`, `self`, `me`, or `_` (unless unused). `func (c *Config)`, not `func (config *Config)`.
  • **Initialisms keep one case.** `URL`, `ID`, `HTTP`, `DB`. Exported: `UserID`, `ServeHTTP`. Unexported: `userID`, `urlPath`. Never `Url`, `Id`, `Http`.
  • **Test doubles end in `Stub` / `Fake` / `Spy` / `Mock`** (or describe behaviour: `AlwaysCharges`, `AlwaysDeclines`).
  • **No `util` / `common` / `helper` / `model` package names.** They invite import renames at every call site. Name by what the package *provides*.
  • **No underscores in identifiers** (except `*_test.go` test/benchmark/example names, and packages imported only by generated code).
  • **Local variable scope ↔ name length.** `i`, `c`, `db` for tight loops; `userCount`, `pollInterval` for file scope. Don't drop letters to save typing (`Sandbox`, not `Sbx`).

Errors

  • **`fmt.Errorf("doing X: %w", err)`** — wrap with `%w` *at the end*, so the chain prints newest→oldest as `outer: middle: inner`.
  • **`%w` only when callers need `errors.Is` / `errors.As`** on the underlying error. Otherwise use `%v`.
  • **`%w` at the start** is for **sentinel** wrappers only: `fmt.Errorf("%w: invalid header", ErrParse)`. Category first, details after.
  • **Sentinel name: `ErrFoo`** at package level: `var ErrNotFound = errors.New("not found")`.
  • **Don't duplicate context** the underlying error already carries. `os.Open` errors already include the path — `fmt.Errorf("could not open settings.txt: %v", err)` is wrong; use a higher-level annotation: `fmt.Errorf("launch codes unavailable: %v", err)`.
  • **Don't add bare "failed: %v" wrappers.** They add no information; just `return err`.
  • **Either log it or return it — not both.** Pick one. Letting the caller log avoids spam.
  • **Error strings: lowercase, no trailing punctuation, no `\n`.** `fmt.Errorf("something bad happened")`, not `"Something bad happened."`.
  • **Cross-process boundaries (gRPC/RPC): use canonical codes** via `status.Errorf(codes.X, ...)` rather than wrapping internal errors raw with `%w`.
  • **`error` is the last return value.** A function taking `context.Context` should usually return `error`.

For more, see `references/errors.md`.

Panics

  • **Don't panic for normal error handling.** Return `error` and multiple return values.
  • **`log.Fatal` over `panic`** for terminal conditions in `main` / `init`. Fatal does not run deferred functions; that's the point.
  • **Panics never cross package boundaries** in public APIs. Convert to `error` at the API edge with a top-level `defer recover()` that re-panics on unknown payloads.
  • **`MustX` is for package-level vars and tests only.** `MustParse`, `template.Must`. Not for runtime user input.
  • **Don't `recover()` to suppress crashes.** Corrupted state propagates further; better is monitoring + crash + fix.
  • **`panic("unreachable")` after `log.Fatalf`** is the idiom — the compiler doesn't know `Fatal` doesn't return.

For more, see `references/panics.md`.

Tests

  • **No assertion libraries / helpers** (`assert.Equal`, `require.NotNil`). Use `if got != want { t.Errorf(...) }`. For complex types: `cmp.Equal` / `cmp.Diff` from `go-cmp`.
  • **`t.Error` over `t.Fatal`** by default — keep going, report all failures in one run. `t.Fatal` only when continuing is meaningless (setup failed, cascading errors would mislead).
  • **Inside `t.Run` subtests: use `t.Fatal`** to skip just that case. Outside subtests in a table loop: `t.Error` + `continue`.
  • **NEVER call `t.Fatal` (`FailNow`, `Fatalf`, `SkipNow`) from a goroutine other than the test's own.** Use `t.Error` from worker goroutines; `t.Fatal` only after `wg.Wait()` from the main goroutine.
  • **Table-driven tests use *named* struct fields**, not positional: `{name: "empty", input: "", want: ""}`.
  • **Test helpers that fail setup call `t.Helper()` + `t.Fatalf`.** This makes the failure point to the *test* line, not the helper line.
  • **Failure message format: `YourFunc(%v) = %v, want %v`** — function name, inputs, got, want, in that order.

For more, see `references/tests.md`.

Variables and strings

  • **`:=` for non-zero init, `var x T` for zero values.** `i := 42`, but `var coords Point` (not `coords := Point{}`).
  • **`var t []string`, not `t := []string{}`** for empty slices. Empty slice and nil slice behave the same for `len`, `cap`, `range`, `append`.
  • **`new(T)` vs `&T{}`**: both are fine for zero values; `new` reads as
Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withgoogle-go-style

A Claude Code plugin that ships a single skill: google-go-style. The skill codifies the Google Go Style Guide into actionable rules that Claude consults whenever you write, review, or refactor Go code.

Get the whole plugin, auto-invoked
Stats
7
Stars
0
Views
1
Forks
Maintained
Maintenance
Shell
Language
Apache-2.0
License
2mo ago
Last commit
2mo ago
Created

Repo: cicdteam/google-go-style