# Go Cheat Sheet: Syntax, Slices, Errors and Goroutines

Source: https://srvscripts.com/guides/go-cheat-sheet/
Updated: 2026-10-09
Publisher: srvScripts (https://srvscripts.com/)

**Short answer:** Start a project with `go mod init example.com/app`, run it with `go run .` and build a static binary with `CGO_ENABLED=0 go build`. Declare with `:=`, loop with `for` (including `for i := range 10`), and return errors as the last value, wrapping them with `fmt.Errorf("...: %w", err)`. Use slices and maps with the `slices` and `maps` packages, goroutines with `sync.WaitGroup`, and `context` for timeouts. Go 1.27 adds generic methods.

The examples in this Go cheat sheet were run with Go 1.27.2 on Linux on 9 October 2026, and checked with `go vet` and `gofmt`.

## The go command

| Command | What it does |
| --- | --- |
| go mod init example.com/app | Create go.mod for a new module |
| go run . | Compile and run the package in the current directory |
| go build -o app . | Build a binary |
| CGO_ENABLED=0 go build -ldflags="-s -w" -o app . | Static binary without debug symbols; copies cleanly to any Linux server |
| GOOS=linux GOARCH=arm64 go build -o app-arm64 . | Cross-compile, e.g. for an ARM server |
| go get example.com/pkg@latest | Add or upgrade a dependency |
| go mod tidy | Add missing and remove unused modules |
| go test ./... | Run all tests; add -race for the race detector, -cover for coverage |
| go vet ./... | Report suspicious code |
| gofmt -l -w . | Format code in place (go fmt ./... does the same) |
| go fix ./... | Apply the modernisers that update code to newer idioms (rewritten in Go 1.26) |
| go install example.com/tool@latest | Install a command into $(go env GOPATH)/bin |
| go doc strings.Fields | Documentation in the terminal |

## Variables, types and control flow

| Syntax | What it does | Example |
| --- | --- | --- |
| x := 42 | Declare and infer the type (inside functions only) | name, port := "web01", 443 |
| var y float64 = 3.5 | Explicit declaration; unset variables get the zero value | var count int // 0 |
| const + iota | Enumerated constants | const ( Low Level = iota; Medium; High ) |
| for i := 0; i < n; i++ | Classic loop; for is Go’s only loop keyword |  |
| for i := range 10 | Loop over an integer (Go 1.22+) |  |
| for i, v := range s | Index and value of a slice, string or map | for k, v := range m |
| for cond { } / for { } | While loop / infinite loop |  |
| if v, err := f(); err != nil | if with a short statement |  |
| switch x { case 1, 2: ... } | No fall-through by default | switch { case n > 10: ... } |
| defer f.Close() | Run when the function returns (LIFO order) |  |
| strconv.Atoi("8080") | String to int, returns (int, error) | strconv.Itoa(80) |

## Slices, maps and strings

| Syntax | What it does |
| --- | --- |
| s := []int{5, 3, 8} | Slice literal |
| make([]int, 0, 100) | Empty slice with capacity 100 |
| s = append(s, 1, 9) | Append; always assign the result back |
| s[1:3] | Sub-slice sharing the same backing array |
| slices.Sort(s), slices.Contains(s, 8), slices.Index(s, 8) | Helpers from the slices package |
| m := map[string]int{"ssh": 22} | Map literal; make(map[string]int) for an empty one |
| v, ok := m["ssh"] | Lookup with presence check (missing keys give the zero value) |
| delete(m, "ssh") | Remove a key |
| slices.Sorted(maps.Keys(m)) | Sorted keys; map iteration order is random |
| strings.Fields(line) | Split on any whitespace |
| strings.Split(s, ","), strings.Join(parts, ",") | Split and join |
| strings.HasPrefix, strings.Contains, strings.TrimSpace | Common tests and trimming |
| var sb strings.Builder | Efficient string building |

Writing to a nil map panics: create it with `make` or a literal first. A sub-slice shares memory with the original, so `append` on one can overwrite the other; use `slices.Clone` when you need a copy.

## Structs, methods and interfaces

```
type Server struct {
    Name string `json:"name"`
    Port int    `json:"port"`
    TLS  bool   `json:"tls,omitempty"`
}

func (s Server) String() string { return fmt.Sprintf("%s:%d", s.Name, s.Port) } // value receiver
func (s *Server) SetPort(p int) { s.Port = p }                                   // pointer receiver modifies

type Shape interface{ Area() float64 }
type Square struct{ Side float64 }

func (q Square) Area() float64 { return q.Side * q.Side } // Square satisfies Shape implicitly

var sh Shape = Square{Side: 3}
switch v := sh.(type) {             // type switch
case Square:
    fmt.Println("square", v.Side)
}
```

| Format verb | Prints |
| --- | --- |
| %v / %+v | Value / value with field names |
| %T | Type name |
| %q | Quoted string |
| %d, %5.2f, %x | Integer, float with width and precision, hex |

## Generics

```
func Max[T cmp.Ordered](a, b T) T {
    if a > b {
        return a
    }
    return b
}

type Stack[T any] struct{ items []T }

func (s *Stack[T]) Push(v T) { s.items = append(s.items, v) }

// Go 1.27: a method can declare its own type parameters
func (s *Stack[T]) Map[U any](f func(T) U) []U {
    out := make([]U, 0, len(s.items))
    for _, v := range s.items {
        out = append(out, f(v))
    }
    return out
}

Max(3, 7)       // 7
Max("a", "b")   // "b"
```

Constraints come from `cmp` (`cmp.Ordered`) or your own interfaces such as `interface{ ~int | ~int64 }`. Interface methods still cannot have type parameters. Go 1.26 also lets `new` take an expression, so `new(5)` returns an `*int` pointing at 5, which is handy for optional JSON fields.

## Errors, defer and panic

| Syntax | What it does |
| --- | --- |
| return 0, err | Errors are ordinary values, returned last |
| errors.New("not found") | Simple error; declare sentinels at package level |
| fmt.Errorf("lookup %q: %w", name, err) | Add context and wrap the original |
| errors.Is(err, ErrNotFound) | Match a sentinel anywhere in the chain |
| errors.As(err, &pathErr) | Extract a specific error type, e.g. *fs.PathError |
| panic(...) / recover() | For programmer bugs only; recover works inside a deferred function |

```
var ErrNotFound = errors.New("not found")

func lookup(name string) (int, error) {
    if name == "ssh" {
        return 22, nil
    }
    return 0, fmt.Errorf("lookup %q: %w", name, ErrNotFound)
}

_, err := lookup("ftp")
fmt.Println(err)                         // lookup "ftp": not found
fmt.Println(errors.Is(err, ErrNotFound)) // true
```

## Goroutines, channels and context

| Syntax | What it does |
| --- | --- |
| go f() | Start a goroutine |
| var wg sync.WaitGroup; wg.Go(fn); wg.Wait() | Run tasks and wait for all (WaitGroup.Go since Go 1.25) |
| ch := make(chan int, 3) | Buffered channel; omit the size for unbuffered |
| ch
