Go Rules Quickstart
10 examples to get you started with Go rules - 7 basic and 3 intermediate.
Search across all documentation pages
10 examples to get you started with Go rules - 7 basic and 3 intermediate.
mkdir rulesdemo && cd rulesdemo && go mod init example.com/rulesdemo.Canonical formatting is the first rule every Go repo shares.
gofmt -w .
test -z "$(gofmt -l .)" || echo "files need formatting"package main
import "fmt"
func main() {fmt.Println("before gofmt")}gofmt removes formatting debate from code review entirely.gofmt -l prints any path.Related: Effective Go as a Living Standard - how official guidance layers with team rules
Go treats errors as values; ignoring them violates core idioms.
package main
import (
"fmt"
"os"
)
func main() {
f, err := os.Open("config.yaml")
if err != nil {
fmt.Fprintf(os.Stderr, "open config: %v\n", err)
os.Exit(1)
}
defer f.Close()
}err from a function call needs an explicit branch.main decides whether to log, wrap, or exit._ discards only when you deliberately accept loss of signal.Related: Errors as Values: Go's Error Philosophy - why errors are not exceptions
Add %w when callers need errors.Is or errors.As.
package demo
import (
"errors"
"fmt"
"io"
)
var ErrNotFound = errors.New("demo: not found")
func Load(r io.Reader) error {
if r == nil {
return fmt.Errorf("load: %w", ErrNotFound)
}
return nil
}load, fetch user).Related: Error Wrapping with %w and errors.As - wrap depth and inspection
IO and RPC functions accept cancellation and deadlines via context.
package demo
import (
"context"
"time"
)
func Fetch(ctx context.Context, id string) error {
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
defer cancel()
// ... use ctx in outbound calls
return nil
}ctx; place it first in the signature.ctx down the stack; do not store it in structs.context.Background() belongs in main, tests, and top-level handlers.Related: Concurrency Rules Checklist - cancellation and ownership rules
Keep function parameters flexible; keep return types specific.
package demo
import "io"
type Store struct{}
func (s *Store) Save(w io.Writer, data []byte) (int, error) {
return w.Write(data)
}
func NewStore() *Store { return &Store{} }io.Writer, io.Reader, or small domain interfaces.*Store avoids surprise behavior behind unnamed interfaces.Related: API Design Rules for Go Libraries - naming and surface rules
Exported identifiers are a compatibility contract.
// Package demo shows minimal godoc on exports.
package demo
// Greeter formats a greeting for name.
// It returns an empty string when name is blank.
func Greeter(name string) string {
if name == "" {
return ""
}
return "hello, " + name
}example_test.go appear in pkg.go.dev.Related: Effective Go Rules Checklist - full idiom list
Vet catches mistakes the compiler allows.
go vet ./...package main
import "fmt"
func main() {
fmt.Printf("%d", "text") // vet: format verb mismatch
}Related: Code Quality Basics - format, vet, and hooks
Encode rule behavior as data so reviewers see cases clearly.
package demo
import "testing"
func TestGreeter(t *testing.T) {
tests := []struct {
name string
in string
want string
}{
{"empty", "", ""},
{"alice", "alice", "hello, alice"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Greeter(tt.in); got != tt.want {
t.Fatalf("got %q want %q", got, tt.want)
}
})
}
}t.Run names that read like checklist items.-race when tests touch goroutines.Related: Table-Driven Tests and Subtests - test structure rules
Hide implementation packages consumers must not import.
rulesdemo/
go.mod
demo/
public.go
internal/
storage/
storage.go// module root imports only public packages; internal is enforced by compiler.
import "example.com/rulesdemo/internal/storage" // fails outside moduleinternal/ paths are rejected by the compiler across module boundaries.internal over documentation alone for "do not import."Related: Package Naming and internal/ Directories - layout rules
Optimization rules assume profiling evidence.
go test -bench=. -benchmem ./...
go test -cpuprofile=cpu.prof -bench=. ./...
go tool pprof -top cpu.profRelated: Performance Rules: When to Optimize - measure-first workflow
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 18, 2026