Way Go Style
Project Setup (AGENTS.md)
Go projects MUST include this skill's Way Specific Conventions in their AGENTS.md file to ensure compliance.
- Reference this skill: Under "Local Skills".
- Copy Conventions: Copy the Way Specific Conventions section below into
AGENTS.md under "Key Conventions".
Way Specific Conventions
- Testing: Use standard
testing and github.com/google/go-cmp/cmp only. No frameworks (Testify, Ginkgo, etc.).
- Linting: Run
GolangCI-Lint v2. Configure via project-specific .golangci.yml.
- Build: Use
way-magefile skill.
- Encore: Use
encore-go-* skills. Encore conventions (e.g., globals) take precedence.
Overview
This skill provides a condensed reference for writing high-quality Go code, synthesizing advice from "Effective Go", Google's "Code Review Comments", and other authoritative sources. It focuses on idiomatic usage, correctness, and maintainability.
Effective Go Idioms
Critical idioms from Effective Go.
Control Flow & Error Handling
- Defer Evaluation: Arguments to deferred functions are evaluated immediately at the call site (not at execution).
- Init Scope: Use
if err := f(); err != nil to restrict variable scope.
- Switch: Use tagless
switch { case condition: ... } instead of long if-else chains.
- Internal Panic/Recover: Use
panic to simplify deep error handling in complex internal code (e.g., parsers), but always recover at the package boundary to return a standard error.
Types & Interfaces
- Functional Adapters: Define methods on function types (e.g.,
type MyFunc func()) to satisfy interfaces. See http.HandlerFunc.
- Interface Verification: Use a global blank assignment to ensure a type satisfies an interface at compile time:
var _ Interface = (*Type)(nil).
Google Style Decisions & Best Practices
Key decisions from the Google Go Style Guide and Code Review Comments.
Core Principles
- Clarity: "Clear to the reader" is priority #1. Explain why, not just what.
- Simplicity: "Least Mechanism". Prefer core constructs (slices, maps) over complex abstractions.
- Concision: High signal-to-noise ratio. Avoid boilerplate.
Naming & Structure
- Packages: Single-word, lowercase (e.g.,
task, not task_manager). Avoid util, common.
- Receivers: 1-2 letter abbreviations (e.g.,
c for Client). NEVER use me, this, self.
- Constants: Always
MixedCaps (e.g., MaxLength), even if exported. NEVER MAX_LENGTH.
- Getters:
Owner() (not GetOwner).
- Interfaces: One-method interfaces ->
Method + -er (e.g., Reader). Define in the consumer package. Keep them small.
Functions & Methods
- Receiver Type:
- Pointer (
*T): If mutating, contains sync.Mutex, or large struct.
- Value (
T): Maps, channels, functions, small immutable structs.
- Consistency: Prefer all pointers or all values for a type's methods.
- Pass Values: Don't pass pointers to small types (
*string, *int) just to save memory.
- Synchronous: Prefer synchronous APIs. Let the caller decide to use goroutines.
- Must Functions:
MustXYZ panic on failure. Use only for package-level init or test helpers.
Error Handling
- Flow: Handle errors immediately (
if err != nil { return err }). Keep "happy path" unindented. Avoid else.
- Structure: Use
%w with fmt.Errorf to wrap errors for programmatic inspection (errors.Is).
- Panics: Never panic in libraries. Return errors.
log.Fatal is okay in main.
- Strings: Lowercase, no punctuation (e.g.,
fmt.Errorf("something bad")) for easy embedding.
Concurrency
- Lifetimes: Never start a goroutine without knowing how it stops.
- Context: Always first arg
ctx context.Context. Never store in structs.
- Copying: Do not copy structs with
sync.Mutex or bytes.Buffer.
Testing
- Framework: Use
testing package. No assertion libraries (use cmp for diffs).
- Helpers: Mark setup/teardown functions with
t.Helper().
- Failure Messages:
YourFunc(%v) = %v, want %v. (Got before Want).
- Table-Driven: Use field names in struct literals for clarity.
- Subtests: Use
t.Run() for clear scope and filtering. Avoid slashes in names.
Global State & Init
- Avoid Globals: Libraries should not rely on package-level vars. Allow clients to instantiate (
New()).
- Initialization: Use
:= for non-zero values. Use var t []T (nil) for empty slices.
- Imports: Group order: Stdlib, Project/Vendor, Side-effects (
_). No . imports.
Practical Go Cheat Sheet
Best practices for maintainable Go from Dave Cheney's Practical Go.
Guiding Principles
- Simplicity, Readability, Productivity: The core values. Clarity > Brevity.
- Identifiers: Choose for clarity. Length proportional to scope/lifespan. Don't include type in name (e.g.,
usersMap -> users).
Design & Structure
- Package Names: Name for what it provides (e.g.,
http), not what it contains. Avoid util, common.
- Project Structure: Prefer fewer, larger packages. Arrange files by import dependency.
- API Design: Hard to misuse. Avoid multiple params of same type. Avoid
nil params.
- Interfaces: Let functions define behavior they require (e.g., take
io.Writer not *os.File).
- Zero Value: Make structs useful without explicit initialization (e.g.,
sync.Mutex, bytes.Buffer).
Concurrency & Errors
- Concurrency: Leave it to the caller. Never start a goroutine without knowing when/how it stops.
- Errors: Eliminate error handling by eliminating errors (e.g.,
bufio.Scanner). Handle errors once (don't log AND return).
- Return Early: Use guard clauses. Keep the "happy path" left-aligned.
Available References
Detailed documentation available in the references/ directory:
- Effective Go: (HTML) The foundational guide to idiomatic Go.
- Code Review Comments: Common comments made during Go code reviews at Google.
- Google Style Guide: Complete set of Google's Go style documents.
- Guide: Core guidelines.
- Decisions: Normative style decisions.
- Best Practices: Evolving guidance.
- Practical Go: Dave Cheney's advice on writing maintainable Go programs.
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: way-go-style3description: Guide for writing idiomatic, effective, and standard Go code. Use this skill when writing, refactoring, or reviewing Go code to ensure adherence to established conventions and best practices. Use when this capability is needed.4---56# Way Go Style78## Project Setup (AGENTS.md)910Go projects MUST include this skill's **Way Specific Conventions** in their `AGENTS.md` file to ensure compliance.11121. **Reference this skill**: Under "Local Skills".132. **Copy Conventions**: Copy the **Way Specific Conventions** section below into `AGENTS.md` under "Key Conventions".1415## Way Specific Conventions1617- **Testing**: Use standard `testing` and `github.com/google/go-cmp/cmp` **only**. No frameworks (Testify, Ginkgo, etc.).18- **Linting**: Run `GolangCI-Lint` v2. Configure via project-specific `.golangci.yml`.19- **Build**: Use `way-magefile` skill.20- **Encore**: Use `encore-go-*` skills. Encore conventions (e.g., globals) take precedence.2122## Overview2324This skill provides a condensed reference for writing high-quality Go code, synthesizing advice from "Effective Go", Google's "Code Review Comments", and other authoritative sources. It focuses on idiomatic usage, correctness, and maintainability.2526## Effective Go Idioms2728Critical idioms from [Effective Go](references/effective_go.html).2930### Control Flow & Error Handling31- **Defer Evaluation:** Arguments to deferred functions are evaluated **immediately** at the call site (not at execution).32- **Init Scope:** Use `if err := f(); err != nil` to restrict variable scope.33- **Switch:** Use tagless `switch { case condition: ... }` instead of long `if-else` chains.34- **Internal Panic/Recover:** Use `panic` to simplify deep error handling in complex internal code (e.g., parsers), but **always** `recover` at the package boundary to return a standard `error`.3536### Types & Interfaces37- **Functional Adapters:** Define methods on function types (e.g., `type MyFunc func()`) to satisfy interfaces. See `http.HandlerFunc`.38- **Interface Verification:** Use a global blank assignment to ensure a type satisfies an interface at compile time: `var _ Interface = (*Type)(nil)`.3940## Google Style Decisions & Best Practices4142Key decisions from the [Google Go Style Guide](references/google/index.md) and [Code Review Comments](references/CodeReviewComments.md).4344### Core Principles45- **Clarity:** "Clear to the reader" is priority #1. Explain *why*, not just *what*.46- **Simplicity:** "Least Mechanism". Prefer core constructs (slices, maps) over complex abstractions.47- **Concision:** High signal-to-noise ratio. Avoid boilerplate.4849### Naming & Structure50- **Packages:** Single-word, lowercase (e.g., `task`, not `task_manager`). **Avoid** `util`, `common`.51- **Receivers:** 1-2 letter abbreviations (e.g., `c` for `Client`). **NEVER** use `me`, `this`, `self`.52- **Constants:** Always `MixedCaps` (e.g., `MaxLength`), even if exported. **NEVER** `MAX_LENGTH`.53- **Getters:** `Owner()` (not `GetOwner`).54- **Interfaces:** One-method interfaces -> `Method` + `-er` (e.g., `Reader`). Define in the **consumer** package. Keep them small.5556### Functions & Methods57- **Receiver Type:**58 - **Pointer (`*T`):** If mutating, contains `sync.Mutex`, or large struct.59 - **Value (`T`):** Maps, channels, functions, small immutable structs.60 - **Consistency:** Prefer all pointers or all values for a type's methods.61- **Pass Values:** Don't pass pointers to small types (`*string`, `*int`) just to save memory.62- **Synchronous:** Prefer synchronous APIs. Let the caller decide to use goroutines.63- **Must Functions:** `MustXYZ` panic on failure. Use **only** for package-level init or test helpers.6465### Error Handling66- **Flow:** Handle errors immediately (`if err != nil { return err }`). Keep "happy path" unindented. Avoid `else`.67- **Structure:** Use `%w` with `fmt.Errorf` to wrap errors for programmatic inspection (`errors.Is`).68- **Panics:** **Never** panic in libraries. Return errors. `log.Fatal` is okay in `main`.69- **Strings:** Lowercase, no punctuation (e.g., `fmt.Errorf("something bad")`) for easy embedding.7071### Concurrency72- **Lifetimes:** Never start a goroutine without knowing how it stops.73- **Context:** Always first arg `ctx context.Context`. **Never** store in structs.74- **Copying:** **Do not copy** structs with `sync.Mutex` or `bytes.Buffer`.7576### Testing77- **Framework:** Use `testing` package. No assertion libraries (use `cmp` for diffs).78- **Helpers:** Mark setup/teardown functions with `t.Helper()`.79- **Failure Messages:** `YourFunc(%v) = %v, want %v`. (Got before Want).80- **Table-Driven:** Use field names in struct literals for clarity.81- **Subtests:** Use `t.Run()` for clear scope and filtering. Avoid slashes in names.8283### Global State & Init84- **Avoid Globals:** Libraries should not rely on package-level vars. Allow clients to instantiate (`New()`).85- **Initialization:** Use `:=` for non-zero values. Use `var t []T` (nil) for empty slices.86- **Imports:** Group order: Stdlib, Project/Vendor, Side-effects (`_`). No `.` imports.8788## Practical Go Cheat Sheet8990Best practices for maintainable Go from **Dave Cheney's** [Practical Go](references/dave-cheney-practical-go.md).9192### Guiding Principles93- **Simplicity, Readability, Productivity:** The core values. Clarity > Brevity.94- **Identifiers:** Choose for clarity. Length proportional to scope/lifespan. Don't include type in name (e.g., `usersMap` -> `users`).9596### Design & Structure97- **Package Names:** Name for what it *provides* (e.g., `http`), not what it contains. Avoid `util`, `common`.98- **Project Structure:** Prefer fewer, larger packages. Arrange files by import dependency.99- **API Design:** Hard to misuse. Avoid multiple params of same type. Avoid `nil` params.100- **Interfaces:** Let functions define behavior they require (e.g., take `io.Writer` not `*os.File`).101- **Zero Value:** Make structs useful without explicit initialization (e.g., `sync.Mutex`, `bytes.Buffer`).102103### Concurrency & Errors104- **Concurrency:** Leave it to the caller. Never start a goroutine without knowing when/how it stops.105- **Errors:** Eliminate error handling by eliminating errors (e.g., `bufio.Scanner`). Handle errors once (don't log AND return).106- **Return Early:** Use guard clauses. Keep the "happy path" left-aligned.107108## Available References109110Detailed documentation available in the `references/` directory:111112- **[Effective Go](references/effective_go.html):** (HTML) The foundational guide to idiomatic Go.113- **[Code Review Comments](references/CodeReviewComments.md):** Common comments made during Go code reviews at Google.114- **[Google Style Guide](references/google/index.md):** Complete set of Google's Go style documents.115 - [Guide](references/google/guide.md): Core guidelines.116 - [Decisions](references/google/decisions.md): Normative style decisions.117 - [Best Practices](references/google/best-practices.md): Evolving guidance.118- **[Practical Go](references/dave-cheney-practical-go.md):** **Dave Cheney's** advice on writing maintainable Go programs.119120---121> Converted and distributed by [TomeVault](https://tomevault.io/claim/way-platform) — claim your Tome and manage your conversions.122<!-- tomevault:4.0:skill_md:2026-04-13 -->