go-dev — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited go-dev (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
At the start of any Go session, detect the project's Go version:
go.mod and extract the go directive (e.g., go 1.26)| Version | Key additions |
|---|---|
| 1.21 | log/slog, slices, maps, min/max/clear builtins, context.AfterFunc, context.WithoutCancel, sync.OnceFunc/OnceValue, PGO auto |
| 1.22 | for i := range n, math/rand/v2, enhanced http.ServeMux routing (method+pattern), loopvar semantic change |
| 1.23 | iter.Seq/iter.Seq2, range-over-func, unique.Handle, structs.HostLayout |
| 1.24 | testing.T.Context, testing.T.Chdir, os.Root, generic type aliases, go tool runs module tools, testing/synctest, omitzero JSON tag |
| 1.25 | sync.WaitGroup.Go, testing.T.Attr, testing.T.Output, sync.Map range-over-func, os.OpenRoot |
| 1.26 | errors.AsType[T], testing.T.ArtifactDir, go test -artifacts, go fix command (21 fixers), new vet analyzers (waitgroup, hostport), new(expr) shorthand |
This is the core of this skill. Go ships a powerful toolchain - use it instead of guessing.
When about to use a stdlib or third-party API you are not certain about, verify the signature first:
go doc <package>.<Symbol> # exact function/type/method
go doc -all <package>.<Type> # full type with all methods
go doc -src <package>.<Symbol> # source code when implementation mattersToken efficiency matters: go doc fmt.Fprintf returns 5 lines. go doc fmt returns hundreds. Always use the most specific query that answers your question.
For third-party packages, they must be importable (in go.mod) before go doc works. For stdlib, it always works.
Pick the verification level that matches the scope of the change:
Full - new files, unfamiliar APIs, concurrency code, public interface changes:
gofmt -d . # format check (should produce no output)
go vet ./... # static analysis
go build ./... # compilation check
go test -race -count=1 ./... # tests with race detector, cache bypassedOr use the bundled script: ${CLAUDE_SKILL_DIR}/scripts/go-quality-check.sh ./...
Standard - modifying existing code in patterns the project already uses:
go vet ./...
go test -count=1 -run TestRelevant ./path/to/pkg/...Light - formatting, comments, documentation, renaming:
gofmt -d <changed-file>Go 1.26 introduced go fix, which applies automated improvements:
go fix -diff ./... # preview changes as unified diff
go fix ./... # apply all fixesThis replaces patterns like interface{} with any, sort.Slice with slices.Sort, manual wg.Add/Done with wg.Go, and many more. Always preview with -diff first.
go test -v -run TestName -count=1 ./pkg/... # verbose, cache-bypassed
go test -race -count=1 ./... # if concurrency is involved
go test -coverprofile=c.out ./... && go tool cover -func=c.out # coverage gapsgo doc on the candidate package to verify its API before committing to itgo get <module>@latest && go mod tidygo mod why <module> to verify it is actually used| Pattern | What it returns |
|---|---|
go doc fmt | Package synopsis |
go doc fmt.Fprintf | Specific function signature and doc |
go doc -all fmt.Stringer | Full type including all methods |
go doc -src fmt.Fprintf | Source code of the function |
go doc -short fmt | One-line per symbol |
go doc -u net/http.Transport | Include unexported fields |
go doc cmd/go | Go command documentation |
| Analyzer | What it catches |
|---|---|
appends | Missing values after append |
assign | Useless assignments |
atomic | Common sync/atomic mistakes |
bools | Boolean operator mistakes |
buildtag | Invalid //go:build directives |
composites | Unkeyed composite literals |
copylocks | Locks passed by value |
defers | Common defer mistakes |
errorsas | Wrong types passed to errors.As |
hostport | Bad address format for net.Dial |
httpresponse | HTTP response handling mistakes |
loopclosure | Loop variable capture in nested functions |
lostcancel | Context cancel function not called |
printf | Printf format string mismatches |
shadow | Variable shadowing (via -vettool) |
slog | Invalid structured logging calls |
stdversion | Uses of too-new stdlib symbols |
structtag | Malformed struct tags |
tests | Mistaken test/example/benchmark signatures |
unmarshal | Non-pointer passed to unmarshal |
unusedresult | Unused results from certain calls |
waitgroup | Misuses of sync.WaitGroup |
(Run go tool vet help for the full list of all 37.)
| Fixer | What it modernizes |
|---|---|
any | interface{} -> any |
fmtappendf | []byte(fmt.Sprintf(...)) -> fmt.Appendf |
forvar | Remove redundant loop variable re-declarations |
mapsloop | Explicit map loops -> maps package calls |
minmax | if/else chains -> min/max builtins |
newexpr | Simplify with new(expr) (1.26) |
omitzero | omitempty -> omitzero for struct fields |
rangeint | 3-clause for -> for i := range n |
slicescontains | Loop searches -> slices.Contains |
slicessort | sort.Slice -> slices.Sort |
stringsbuilder | String concatenation += -> strings.Builder |
stringscut | strings.Index patterns -> strings.Cut |
stringscutprefix | HasPrefix/TrimPrefix -> CutPrefix |
stringsseq | Split/Fields ranges -> SplitSeq/FieldsSeq iterators |
testingcontext | context.WithCancel in tests -> t.Context() |
waitgroup | wg.Add(1); go func() { defer wg.Done()... } -> wg.Go(f) |
(Run go tool fix help for the full list.)
| Flag | Purpose |
|---|---|
-race | Enable race detector |
-count=1 | Bypass test cache |
-run <regex> | Run only matching tests |
-v | Verbose output |
-short | Skip long-running tests (tests check testing.Short()) |
-shuffle=on | Randomize test order |
-failfast | Stop on first failure |
-cover | Enable coverage analysis |
-coverprofile=f | Write coverage profile to file |
-coverpkg=pattern | Apply coverage to matching packages |
-bench=<regex> | Run matching benchmarks |
-benchmem | Report allocations in benchmarks |
-benchtime=5s | Benchmark duration |
-fuzz=<regex> | Run matching fuzz tests |
-timeout=10m | Test timeout (default 10m) |
-cpuprofile=f | Write CPU profile |
-memprofile=f | Write memory profile |
-artifacts | Store test artifacts in output directory (1.26+) |
| Flag | Purpose |
|---|---|
-race | Enable race detector |
-pgo=auto | Profile-guided optimization (auto uses default.pgo) |
-gcflags='-m' | Show escape analysis |
-gcflags='-S' | Show assembly output |
-ldflags='-s -w' | Strip debug info (smaller binary) |
-ldflags='-X main.version=v1.0' | Embed build-time values |
-trimpath | Remove filesystem paths from binary |
-tags=<list> | Build constraint tags |
-o <file> | Output file path |
| Command | Purpose |
|---|---|
go mod tidy | Sync go.mod/go.sum with imports |
go mod download | Download modules to cache |
go mod graph | Print module dependency graph |
go mod vendor | Create vendored copy |
go mod verify | Verify dependencies match go.sum |
go mod why <mod> | Explain why a module is needed |
go mod edit -go=1.26 | Update go directive |
| Flag | Purpose |
|---|---|
-d | Print diff (do not modify files) |
-l | List files with formatting differences |
-s | Simplify code |
-w | Write changes to files |
Check availability before use. These are not part of the Go toolchain:
| Tool | Check | Purpose |
|---|---|---|
staticcheck | which staticcheck | Extended static analysis beyond go vet |
golangci-lint | which golangci-lint | Meta-linter running 100+ linters |
govulncheck | which govulncheck | Scan dependencies for known vulnerabilities |
If unavailable, go vet covers the most critical checks. Do not block on missing external tools.
| Diagnostic | Cause | Fix | Reference |
|---|---|---|---|
declared and not used | Unused variable | Remove it or use it | - |
imported and not used | Unused import | Remove import; use _ alias only during active development | - |
cannot use X as type Y | Type mismatch | Run go doc on both types; check interface satisfaction | references/interfaces-and-design.md |
data race detected | Concurrent unsynchronized access | Use mutex, channel, or atomic; see concurrency patterns | references/concurrency.md |
err is shadowed during return | := in inner scope shadows outer err | Use = instead of := or rename inner variable | references/error-handling.md |
loop variable X captured by func literal | Pre-1.22 loop var capture | Go 1.22+ fixes this; for older: copy variable before closure | - |
possible misuse of sync.WaitGroup | Add called inside goroutine | Call Add before starting goroutine, not inside it | references/concurrency.md |
context.Background used in long-lived operation | Missing context propagation | Accept context.Context as first parameter; pass from caller | references/concurrency.md |
go directive in go.mod too old | go.mod version < required feature | Run go mod edit -go=<version> to update | references/modules-and-deps.md |
Any ioutil.* usage | Deprecated since Go 1.16 | ioutil.ReadAll -> io.ReadAll; ioutil.ReadFile -> os.ReadFile; etc. | references/modern-go.md |
| HTTP handler decodes body without size limit | DoS via unbounded request body | Wrap r.Body with http.MaxBytesReader(w, r.Body, maxBytes) | references/security.md |
http.Server{} without timeouts | Vulnerable to slowloris attacks | Set ReadTimeout, WriteTimeout, IdleTimeout | references/security.md |
These are the rules for when to use tools without being asked:
go doc <pkg>.<Symbol> before claiming any API signature you have not used in this session. This is the single most important behavior - wrong signatures waste the user's time.go vet ./... after creating new files, adding exported functions, or modifying concurrency code.gofmt -d <file> before presenting code as complete. If it produces output, the code has formatting issues.go test -race -count=1 ./... after modifying code involving goroutines, channels, shared state, or sync primitives.go directive in go.mod before suggesting features from newer versions. Use the version feature table above.go fix -diff ./... to identify modernization opportunities. Present the diff to the user before applying.ioutil (deprecated 1.16), math/rand.Seed (unnecessary since 1.20), // +build (replaced by //go:build).errors.AsType[T] on Go 1.26+.http.MaxBytesReader to prevent denial-of-service via unbounded uploads. This is easy to forget and hard to catch in code review.http.Server, always set ReadTimeout, WriteTimeout, and IdleTimeout. A server without timeouts is vulnerable to slowloris attacks.When NOT to run tools:
go test when only editing comments or documentationgo vet when the user is just asking a question, not writing codego doc for universally known functions (fmt.Println, len, append, etc.)These are the philosophical foundations. When reviewing or writing Go code, apply these as judgment calls, not rigid rules:
fmt.Errorf("doing X: %w", err). See references/error-handling.md.sync.Mutex, bytes.Buffer).user package, not a models package.defer immediately after acquiring a resource. It communicates cleanup intent right where the resource is opened.Open the reference file that matches the question. Load only one at a time.
errors.Is/As/AsType, errors.Join) -> references/error-handling.mdreferences/concurrency.mdreferences/testing.mdgo fix guide) -> references/modern-go.mdreferences/performance.mdreferences/interfaces-and-design.mdreferences/modules-and-deps.mdreferences/security.mdFor a problem-based router ("I need to..."), see references/_index.md.
Before declaring work done on Go code:
gofmt -d . produces no outputgo vet ./... produces no diagnosticsgo build ./... succeedsgo test -race -count=1 ./... passesioutil, math/rand.Seed, // +build)%w where callers need errors.Is/errors.Ascontext.Context is threaded through where cancellation mattershttp.MaxBytesReader for request body limitsReadTimeout, WriteTimeout, IdleTimeout setgo mod tidy has been run if dependencies changed~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.