go-conventionslisted
Install: claude install-skill andr-ca/agentharness
# Go Conventions
This file is self-contained for day-to-day use. Deeper reference (needs
the full harness checkout): `languages/go/CONVENTIONS.md` (full examples
including godoc comments, context-first concurrency, and table-driven
tests).
## Naming
- Unexported: `camelCase`. Exported: `PascalCase`.
- Interfaces: singular, behavior-describing name (`Reader`, `Storer`,
`UserRepository` — not `IUserRepository`).
- Error sentinels: `Err` prefix (`ErrNotFound`, `ErrTimeout`).
- Receiver: one or two letters, the type's initials (`u *User`, not
`user *User`). Keep consistent across all methods of a type.
## Errors: wrap with context, return early
```go
// Wrap to preserve the stack — don't swallow context
if err != nil {
return fmt.Errorf("getUserByID %q: %w", id, err)
}
// Return early — avoid deep nesting
func process(ctx context.Context, id string) error {
user, err := repo.Find(ctx, id)
if err != nil {
return fmt.Errorf("process: find user: %w", err)
}
// ... rest of the logic at the same indent level
}
```
## Interfaces: define at the point of use
Declare the interface in the package that uses it, not the package that
implements it. A concrete type's package need not know about the
interface — `io.Reader` doesn't live in the `os` package, and
`UserRepository` should live in the handler/service that calls it, not
in the `postgres` package that provides one.
## Pitfalls to catch in review
```go
// Goroutine leak — if nothing reads from r