feat(skills): add coding-dev.md and per-language rules under code-languages/
Generic coding rules and preferences distilled from existing agent rule files, project AGENTS.md/.rules, and saved memories: - strictness maximal; suppressions must be reported to the user - never filter build/lint/test output through grep/tail/head - reuse > fork > self-implement; generic code becomes its own package - 1000-line file / 100-line function limits, split by concern - regression test every fixed bug; never test against real user data - events over polling; scope discipline; honest reporting Per-language: rust, js-typescript, bash, python, go, csharp-dotnet, c-cpp. Each extends coding-dev.md rather than repeating it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ba95f171b2
commit
57968904bf
9 files changed
+1499
-1
No files matched your search
@@ -0,0 +1,157 @@
|
||||
---
|
||||
name: go
|
||||
description: >-
|
||||
Use this skill when writing, building, linting, testing, or releasing Go — including
|
||||
golangci-lint configuration, strict typing over map[string]interface{}, official SDK
|
||||
preference, CGO-free static builds, context handling, and the build gate.
|
||||
---
|
||||
|
||||
# Go — Rules & Preferences
|
||||
|
||||
Extends [`../coding-dev.md`](../coding-dev.md). Everything there applies; this adds Go specifics.
|
||||
|
||||
---
|
||||
|
||||
## 1. The Gate
|
||||
|
||||
```bash
|
||||
gofmt -l . # must print nothing
|
||||
go vet ./...
|
||||
golangci-lint run
|
||||
go test -race ./...
|
||||
go build ./...
|
||||
```
|
||||
|
||||
Wire this into a single entry point (`make check`, `scripts/build.sh`) so it cannot be
|
||||
partially run. **A skipped test fails the gate.** Add `govulncheck` for binary vulnerability
|
||||
scanning on anything that ships.
|
||||
|
||||
---
|
||||
|
||||
## 2. Linting — Strict Set
|
||||
|
||||
`golangci-lint` with a deliberately broad selection, not the defaults:
|
||||
|
||||
```yaml
|
||||
linters:
|
||||
enable:
|
||||
- staticcheck
|
||||
- errcheck # every returned error is handled
|
||||
- gosec # security findings
|
||||
- noctx # no HTTP request without a context
|
||||
- revive
|
||||
- misspell
|
||||
- unconvert
|
||||
- bodyclose # every response body is closed
|
||||
- goconst
|
||||
- ineffassign
|
||||
- nilerr
|
||||
```
|
||||
|
||||
`errcheck` and `bodyclose` catch the two most common real Go bugs. As always: fix rather than
|
||||
suppress, and when suppressing use a specific `//nolint:name // reason` with the reason.
|
||||
|
||||
---
|
||||
|
||||
## 3. Typing — Concrete, Not Dynamic
|
||||
|
||||
- **Strongly typed structs everywhere.** Avoid `map[string]interface{}` and reflection when a
|
||||
struct can be defined — including for JSON, config, and API payloads.
|
||||
- **Typed constants/enums**, not bare strings:
|
||||
```go
|
||||
type SyncStatus string
|
||||
|
||||
const (
|
||||
StatusSynced SyncStatus = "synced"
|
||||
StatusOutdated SyncStatus = "outdated"
|
||||
StatusDirty SyncStatus = "dirty"
|
||||
)
|
||||
```
|
||||
- **Concrete error types** with `errors.Is` / `errors.As`, not string comparison.
|
||||
- Keep types shared with a frontend structurally in sync with that frontend's types; when both
|
||||
exist, a change to one is incomplete without the other.
|
||||
|
||||
---
|
||||
|
||||
## 4. Errors
|
||||
|
||||
- **Every error is handled.** `errcheck` enforces it; do not `_ =` an error away without a
|
||||
comment explaining why it cannot matter.
|
||||
- Wrap with context: `fmt.Errorf("fetching %s: %w", name, err)`. Always `%w`, never `%v`, when
|
||||
the caller might need to inspect it.
|
||||
- Sentinel errors as package-level `var ErrNotFound = errors.New(...)`; typed errors when the
|
||||
caller needs data from them.
|
||||
- **`panic` only for genuinely unrecoverable programmer error**, never for expected runtime
|
||||
conditions. A library never panics on input it was designed to receive.
|
||||
- `defer` the cleanup immediately after acquiring the resource, always.
|
||||
|
||||
---
|
||||
|
||||
## 5. Context
|
||||
|
||||
- **Every function that does I/O takes `ctx context.Context` as its first parameter.**
|
||||
- Never store a context in a struct field.
|
||||
- Never pass `nil` — `context.TODO()` marks a genuine gap.
|
||||
- Honor cancellation: select on `ctx.Done()` in loops, and pass ctx down to every HTTP call
|
||||
(`noctx` enforces this).
|
||||
- Set timeouts on outbound requests. A default `http.Client` has no timeout at all.
|
||||
|
||||
---
|
||||
|
||||
## 6. Dependencies — Official SDKs First
|
||||
|
||||
Follow the global reuse-first ordering. In Go, strongly prefer **official/first-party SDKs**
|
||||
over third-party wrappers — they track API changes and handle auth and pagination correctly.
|
||||
|
||||
Choose **pure-Go implementations over CGO ones** whenever the trade is acceptable: a CGO
|
||||
dependency turns a static single-binary build into a toolchain and glibc problem, and rules
|
||||
out a `FROM scratch`/Alpine container image.
|
||||
|
||||
```bash
|
||||
CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o bin/app ./cmd/app
|
||||
```
|
||||
|
||||
`go mod tidy` before committing, and commit `go.sum`.
|
||||
|
||||
---
|
||||
|
||||
## 7. Concurrency
|
||||
|
||||
- **Share memory by communicating.** Channels for handoff; `sync.Mutex` for guarding a struct's
|
||||
own fields. Don't mix both for the same state.
|
||||
- **`go test -race` is not optional** — it belongs in the gate, not in an occasional manual run.
|
||||
- Every goroutine has a defined exit path. `errgroup.Group` for a set of related goroutines so
|
||||
errors propagate and cancellation fans out.
|
||||
- **Events over polling** — subscribe to a watch/notify API rather than looping on a ticker.
|
||||
Where a ticker is genuinely necessary, make the interval configurable and document why.
|
||||
- Never leak a goroutine on a channel nobody reads.
|
||||
|
||||
---
|
||||
|
||||
## 8. Structure
|
||||
|
||||
- `cmd/<binary>/` for entry points; `pkg/` or `internal/` for the actual code.
|
||||
- `internal/` for anything that must not become public API — it is compiler-enforced.
|
||||
- One package per concern; **package names are lowercase, single-word, no underscores**, and
|
||||
never `util` or `common`.
|
||||
- Keep the exported surface small. Unexported by default.
|
||||
- Embed frontend/static assets with `//go:embed` for single-binary distribution.
|
||||
- File and function size limits from the general rules apply.
|
||||
|
||||
---
|
||||
|
||||
## 9. Testing
|
||||
|
||||
- Table-driven tests are the default idiom.
|
||||
- `t.Parallel()` where tests are genuinely independent.
|
||||
- `t.TempDir()` for filesystem work — it cleans itself up.
|
||||
- `httptest` for HTTP handlers and for faking upstreams; do not hit real services in unit tests.
|
||||
- **Regression test every fixed bug.**
|
||||
- **Never run destructive operations against real accounts or user data during validation** —
|
||||
temporary fixtures only.
|
||||
|
||||
---
|
||||
|
||||
## 10. Related
|
||||
- [`../coding-dev.md`](../coding-dev.md) — the general rules this extends.
|
||||
- [`js-typescript.md`](./js-typescript.md) — for the embedded frontend in a Go service.
|
||||
Reference in new issue
Block a user