[TERMINAL · SKILLS]
> mounting /skills...
> indexing skill manifests...
> linking agents: claude · codex · gemini · cursor
> ready.
[░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 0%
>

Go

Go is Google's open-source programming language whose toolchain compiles programs into single static binaries and ships with built-in modules, testing, fuzzing, race detection and cross-compilation. Use when a user asks to set up a Go project, add or upgrade Go dependencies, run go test, go vet or benchmarks, fix a data race, write generic Go code, work across several modules with go.work, or build release binaries for Linux, macOS and Windows. Phrases: "init a go module", "go mod tidy", "cross-compile my Go CLI", "why is my go test cached", "build a static Go binary for Docker".

#go#golang#go-modules#cross-compilation#testing
terminal-skillsv1.0.0
Works with:claude-codeopenai-codexgemini-clicursor
Source
Trust Score
87/ 100
2.67×
Impact

Validation

Quality
87/ 100
Does it follow best practices?
4 PASS · 2 WEAK
Security
Passed
No known issues
Content review + injection scan
Impact
2.67×
33% → 88% agent success
Avg across 3 eval scenarios
Scored 9/30/2026 · skill v1.0.0
agent@terminalskills — playground
full playground →

Prove Go on your task

simulated preview
$
$

real run in an isolated sandbox · files auto-deleted after 7 days · nothing touches your machine

$
✓ Installed golang v1.0.0

Getting Started

  1. Install the skill using the command above
  2. Open your AI coding agent (Claude Code, Codex, Gemini CLI, or Cursor)
  3. Reference the skill in your prompt
  4. The AI will use the skill's capabilities automatically

Example Prompts

  • "Review the open pull requests and summarize what needs attention"
  • "Generate a changelog from the last 20 commits on the main branch"

Documentation

Overview

Go is a compiled, garbage-collected language with a single go command that handles everything a project needs: dependency management (modules), building, testing, benchmarking, fuzzing, static analysis (go vet), code rewrites (go fix) and cross-compilation. A build produces one self-contained executable, so a Go program ships as one file with no runtime to install on the target.

This skill covers the language toolchain itself. For HTTP frameworks use the gin, go-echo or go-fiber skills; for CLI command trees use cobra. The current stable release is Go 1.27 (August 2026); Go supports the two most recent major releases (1.27 and 1.26).

Instructions

Install Go

Package managers first:

bash
brew install go            # macOS
winget install GoLang.Go   # Windows (PowerShell)

On Linux, download the archive from go.dev, check it against the SHA-256 listed on https://go.dev/dl/, then extract it to /usr/local. If an older Go already lives in /usr/local/go, remove that directory first: the docs warn that extracting over an old tree produces a broken install.

bash
curl -LO https://go.dev/dl/go1.27.1.linux-amd64.tar.gz
sha256sum go1.27.1.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.27.1.linux-amd64.tar.gz

Add the toolchain and installed tools to PATH (in ~/.profile, ~/.bashrc or ~/.zshrc), open a new shell and verify:

bash
export PATH=$PATH:/usr/local/go/bin
export PATH="$PATH:$(go env GOPATH)/bin"
go version

Start a module

A module is a directory tree with a go.mod at its root. The module path is normally the repository URL.

bash
mkdir -p ratelimit/cmd/rlcheck && cd ratelimit
go mod init github.com/northwind-labs/ratelimit

go.mod records the module path and the minimum Go version (go 1.27.1). Library code sits at the root; each executable gets its own package main directory under cmd/ (here cmd/rlcheck/).

Build, run and format

bash
go run ./cmd/rlcheck -burst 5      # compile and run in one step
go build -o bin/rlcheck ./cmd/rlcheck
gofmt -l . && gofmt -w .           # list, then fix, unformatted files
go vet ./...                       # ./... = every package below here; flags printf misuse, copied locks

Manage dependencies

bash
go get golang.org/x/sync@latest      # add or upgrade one module
go get golang.org/x/sync@v0.23.0     # pin an exact version
go mod tidy                          # add missing, drop unused requirements
go list -m -u all                    # show modules with newer versions in [brackets]
go mod why golang.org/x/sync/errgroup  # which import pulls this in

go.sum holds checksums for every downloaded module; commit it together with go.mod. For private repositories, set GOPRIVATE=github.com/northwind-labs/* so the go command fetches them directly instead of through the public proxy and checksum database.

Tool dependencies (Go 1.24+)

Pin developer tools in go.mod instead of installing them globally, so every contributor and CI job runs the same version:

bash
go get -tool golang.org/x/vuln/cmd/govulncheck@latest
go tool govulncheck ./...

This adds a tool golang.org/x/vuln/cmd/govulncheck line to go.mod. To install a program on your machine instead, use go install golang.org/x/tools/gopls@latest; binaries land in $(go env GOPATH)/bin (or $GOBIN).

Test, benchmark, fuzz

Tests live in *_test.go files next to the code. A table-driven test with subtests:

go
func TestAllow(t *testing.T) {
	tests := []struct {
		name  string
		burst int
		calls int
		want  int
	}{
		{"within burst", 5, 3, 3},
		{"exceeds burst", 5, 8, 5},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			l := New(tt.burst, 1)
			got := 0
			for range tt.calls {
				if l.Allow() {
					got++
				}
			}
			if got != tt.want {
				t.Errorf("allowed %d, want %d", got, tt.want)
			}
		})
	}
}

func BenchmarkAllow(b *testing.B) {
	l := New(1_000_000, 1_000_000)
	for b.Loop() {
		l.Allow()
	}
}
bash
go test ./...                              # all packages; results are cached
go test -count=1 ./...                     # bypass the test cache
go test -run 'TestAllow/exceeds' -v .      # one subtest (spaces become _)
go test -race ./...                        # data race detector
go test -coverprofile=cover.out ./... && go tool cover -func=cover.out
go test -bench=Allow -benchmem -run='^$' . # benchmarks only
go test -fuzz=FuzzMax -fuzztime=30s .      # fuzz one target

A fuzz target starts with Fuzz, seeds inputs with f.Add and checks a property in f.Fuzz. Failing inputs are saved under testdata/fuzz/ and replayed by every later go test.

Generics

Type parameters work on functions and types; cmp.Ordered and comparable cover most constraints.

go
// imports: cmp, slices
func TopN[T cmp.Ordered](xs []T, n int) []T {
	s := slices.Clone(xs)
	slices.SortFunc(s, func(a, b T) int { return cmp.Compare(b, a) })
	return s[:min(n, len(s))]
}

type Set[K comparable] map[K]struct{}

func (s Set[K]) Add(k K)      { s[k] = struct{}{} }
func (s Set[K]) Has(k K) bool { _, ok := s[k]; return ok }

Go 1.27 also allows methods to declare their own type parameters (func (b Box) Scale[T int | float64](f T) T); such code needs go 1.27 in go.mod.

Multi-module workspaces

When a service and a library live in separate modules and you change both at once:

bash
go work init ./gateway ./ratelimit
go work use ./billing        # add another module later
go run ./gateway

go.work makes the local copies win over the versions in each go.mod, so there is no replace directive to forget. Usually keep it out of the repository.

Cross-compile release binaries

Set GOOS/GOARCH to build for another platform; go tool dist list shows every supported pair. CGO_ENABLED=0 gives a fully static binary with no libc dependency.

bash
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath \
  -ldflags "-s -w -X main.version=v1.4.0" -o dist/rlcheck-linux-arm64 ./cmd/rlcheck
  • -trimpath strips local file paths from the binary.
  • -ldflags "-s -w" drops symbol and debug tables (smaller file).
  • -X main.version=v1.4.0 sets a package-level var version string at link time.
  • go version -m dist/rlcheck-linux-arm64 prints the Go version, module versions and build settings embedded in any Go binary.

Examples

Example 1: Ship a CLI to four platforms

User request: "Build our rlcheck tool for Linux (x86 and ARM), Apple Silicon Macs and Windows, stamped with version v1.4.0."

bash
for target in linux/amd64 linux/arm64 darwin/arm64 windows/amd64; do
  os=${target%/*}; arch=${target#*/}; ext=""
  [ "$os" = windows ] && ext=.exe
  CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -trimpath \
    -ldflags "-s -w -X main.version=v1.4.0" \
    -o "dist/rlcheck-$os-$arch$ext" ./cmd/rlcheck
done
file dist/*
./dist/rlcheck-linux-amd64 -version

Result: four files of about 1.6 MB each. file reports ELF 64-bit ... statically linked, stripped for the Linux builds, Mach-O 64-bit arm64 executable for macOS and PE32+ executable (console) x86-64 for Windows. The Linux binary prints rlcheck v1.4.0. Nothing else has to be installed on the target machines.

Example 2: Add a dependency, test for races and scan for vulnerabilities

User request: "Our health checker should probe hosts in parallel, at most 4 at a time. Add that, make sure there are no races, and check dependencies for known CVEs before we merge."

go
package main

import (
	"context"

	"golang.org/x/sync/errgroup"
)

func checkAll(ctx context.Context, hosts []string, check func(context.Context, string) error) error {
	g, ctx := errgroup.WithContext(ctx)
	g.SetLimit(4)
	for _, h := range hosts {
		g.Go(func() error { return check(ctx, h) })
	}
	return g.Wait()
}
bash
go get golang.org/x/sync@latest
go mod tidy
go vet ./...
go test -race -count=1 ./...
go get -tool golang.org/x/vuln/cmd/govulncheck@latest
go tool govulncheck ./...

Result: go.mod gains require golang.org/x/sync v0.23.0 and a tool line for govulncheck. go test -race prints ok for each package, or a WARNING: DATA RACE report with both goroutines' stacks. govulncheck ends with No vulnerabilities found. or lists each vulnerable call it actually reaches, with the fixed version.

Example 3: Small image for a Go API in Docker

User request: "Our Go gateway image is almost 1 GB because it ships the whole toolchain. Make it small."

dockerfile
FROM golang:1.27-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -o /out/gateway ./cmd/gateway

FROM gcr.io/distroless/static-debian13:nonroot
COPY --from=build /out/gateway /gateway
ENTRYPOINT ["/gateway"]

Result: go mod download sits in its own layer, so it is cached until go.mod/go.sum change. The final image contains only the static binary on a distroless base and runs as a non-root user, a small fraction of the size of the full golang image.

Guidelines

  • Run gofmt, go vet ./... and go test -race ./... in CI. The race detector only finds races on code paths the tests actually execute; it requires cgo (CGO_ENABLED=1) and a supported target such as linux/amd64, darwin/arm64 or windows/amd64.
  • go test caches passing results for unchanged code (it does notice changed files in the module and changed environment variables). Use -count=1 when a test depends on external state such as a database or network service.
  • Commit go.mod and go.sum together, and run go mod tidy before committing. Do not edit go.sum by hand.
  • go install pkg@version ignores the current module's go.mod; use it for machine-wide tools. Use go get -tool for tools the project depends on.
  • CGO_ENABLED=0 fails for packages that need C (some SQLite drivers, for example). Pick a pure-Go alternative or cross-compile with a C toolchain for the target.
  • -X only sets string variables, and needs the full import path for non-main packages (-X github.com/northwind-labs/ratelimit/internal/build.Version=v1.4.0).
  • Private module credentials belong in git's credential helper or ~/.netrc, never in go.mod or the source tree.
  • The go line in go.mod is the minimum Go version; raise it with go get go@1.27.1. With the default GOTOOLCHAIN=auto an older go command downloads the required toolchain; set GOTOOLCHAIN=local in CI to fail instead.
  • go fix ./... rewrites code to newer idioms; review the diff first with go fix -diff ./....
  • When not to use Go: hard-real-time or GC-sensitive hot paths (look at Rust), quick data analysis (Python), or browser UI code.