/user/kayd @ devops :~$ cat golang.md

Go (Golang) Cheatsheet Go (Golang) Cheatsheet

QR Code linking to: Go (Golang) Cheatsheet
Karandeep Singh
Karandeep Singh
• 6 minutes

Summary

A practical Go reference for DevOps work covering go mod and build commands, core syntax, concurrency patterns, testing, and the stdlib snippets I reuse most.

Docker, Kubernetes, Terraform, and half the CLIs I touch daily are written in Go, so it became my default for tooling too. These are the notes I wish I’d had when I started: toolchain commands, syntax I keep forgetting, and the concurrency patterns that actually come up in DevOps work.

Toolchain

Docs: go command on pkg.go.dev

go mod init github.com/karan/myapp        # Start a module
go mod tidy                               # Add missing / drop unused deps
go get github.com/spf13/cobra@latest      # Add or upgrade a dependency
go run .                                  # Compile + run current package
go build -o bin/myapp ./cmd/myapp         # Build a binary
go test ./...                             # Test everything, recursively
go test -run TestParse -v ./internal/...  # One test, verbose
go test -race -cover ./...                # Race detector + coverage
go vet ./...                              # Static analysis
gofmt -l -w .                             # Format (or: go fmt ./...)
go install golang.org/x/tools/cmd/goimports@latest   # Install a tool to $GOBIN
GOOS=linux GOARCH=arm64 go build -o myapp-arm64 .    # Cross-compile
go build -ldflags="-s -w" .               # Strip symbols, smaller binary

Static cross-compiled binaries are why Go containers are tiny; the multi-stage build in my Docker Cheatsheet shows the payoff.

Syntax Essentials

Docs: The Go language specification at go.dev

Types, Variables, Slices, Maps

var count int = 10        // explicit
name := "karan"           // inferred, function scope only
const MaxRetries = 3      // constants: untyped until used

nums := []int{1, 2, 3}                 // slice
nums = append(nums, 4)
sub := nums[1:3]                       // [2 3] - shares backing array

ports := map[string]int{"http": 80, "https": 443}
ports["ssh"] = 22
v, ok := ports["ftp"]                  // ok == false: key absent
delete(ports, "ssh")

for i, n := range nums { fmt.Println(i, n) }    // map range order is random

Structs, Methods, Interfaces

type Server struct {
    Host string
    Port int
    tags []string          // lowercase = unexported
}

// Value receiver: gets a copy. Pointer receiver: can mutate.
func (s Server) Addr() string      { return fmt.Sprintf("%s:%d", s.Host, s.Port) }
func (s *Server) AddTag(t string)  { s.tags = append(s.tags, t) }

type Notifier interface {
    Notify(msg string) error
}

// Interfaces are satisfied implicitly - no "implements" keyword.
type SlackNotifier struct{ Webhook string }

func (s SlackNotifier) Notify(msg string) error { return post(s.Webhook, msg) }

func alert(n Notifier, msg string) error { return n.Notify(msg) }

Errors & Defer

f, err := os.Open("config.yaml")
if err != nil {
    return fmt.Errorf("opening config: %w", err)   // %w wraps for errors.Is/As
}
defer f.Close()          // runs when the function returns, LIFO order

if errors.Is(err, os.ErrNotExist) { /* fall back to defaults */ }

var pathErr *os.PathError
if errors.As(err, &pathErr) { fmt.Println(pathErr.Path) }

var ErrNotFound = errors.New("not found")   // sentinel error

Goroutines & Channels

Docs: Effective Go on go.dev

go doWork()                        // fire-and-forget goroutine

ch := make(chan string)            // unbuffered: send blocks until receive
buf := make(chan int, 10)          // buffered: blocks only when full

ch <- "ping"; msg := <-ch          // send / receive
close(ch)                          // sender closes; receivers range safely

for msg := range ch { fmt.Println(msg) }   // loop until channel closed

select

select {
case msg := <-ch:
    fmt.Println("got", msg)
case <-time.After(2 * time.Second):
    fmt.Println("timeout")
case <-ctx.Done():
    return ctx.Err()
}

WaitGroup

var wg sync.WaitGroup
for _, host := range hosts {
    wg.Add(1)
    go func(h string) {
        defer wg.Done()
        checkHealth(h)
    }(host)
}
wg.Wait()

Context Cancelation

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
resp, err := http.DefaultClient.Do(req)   // aborts when ctx expires

// In workers, select on ctx.Done() alongside your jobs channel and
// return ctx.Err() when it fires - same pattern as the select above.

Table-Driven Tests

Docs: testing package on pkg.go.dev

func TestParsePort(t *testing.T) {
    tests := []struct {
        name    string
        input   string
        want    int
        wantErr bool
    }{
        {"plain", "8080", 8080, false},
        {"with colon", ":443", 443, false},
        {"garbage", "abc", 0, true},
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := ParsePort(tt.input)
            if (err != nil) != tt.wantErr {
                t.Fatalf("err = %v, wantErr %v", err, tt.wantErr)
            }
            if got != tt.want {
                t.Errorf("got %d, want %d", got, tt.want)
            }
        })
    }
}

Generics (Quick Example)

Docs: Generics tutorial on go.dev

func Map[T, U any](in []T, f func(T) U) []U {
    out := make([]U, len(in))
    for i, v := range in {
        out[i] = f(v)
    }
    return out
}

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

names := Map(servers, func(s Server) string { return s.Addr() })

Formatting Verbs

Docs: fmt package on pkg.go.dev

VerbMeaningExample output
%vDefault format{web 8080}
%+vStruct with field names{Host:web Port:8080}
%#vGo syntax representationmain.Server{Host:"web", ...}
%TType of the valuemain.Server
%dInteger (base 10)8080
%sStringweb
%qQuoted string"web"
%f / %.2fFloat / 2 decimals3.14
%xHex1f90
%wWrap error (fmt.Errorf only)-

Common Stdlib Snippets

Docs: Standard library on pkg.go.dev

net/http Server

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("ok"))
    })
    srv := &http.Server{Addr: ":8080", Handler: mux, ReadTimeout: 5 * time.Second}
    log.Fatal(srv.ListenAndServe())
}

JSON Marshal / Unmarshal

type Alert struct {
    Name     string    `json:"name"`
    Severity string    `json:"severity,omitempty"`
    FiredAt  time.Time `json:"fired_at"`
}

b, err := json.Marshal(alert)              // struct → []byte
err = json.Unmarshal(b, &alert)            // []byte → struct
err = json.NewDecoder(r.Body).Decode(&alert)   // straight from an io.Reader

os/exec

out, err := exec.Command("kubectl", "get", "pods", "-o", "json").Output()
if err != nil {
    var exitErr *exec.ExitError
    if errors.As(err, &exitErr) {
        log.Printf("exit %d: %s", exitErr.ExitCode(), exitErr.Stderr)
    }
}

cmd := exec.CommandContext(ctx, "sh", "-c", "long-running-task")   // killable via ctx
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
err = cmd.Run()

time

now := time.Now()
now.Format(time.RFC3339)                          // 2025-07-23T09:09:00Z
t, _ := time.Parse("2006-01-02", "2025-07-23")    // reference date layout
elapsed := time.Since(start)

ticker := time.NewTicker(30 * time.Second)   // defer ticker.Stop()
for range ticker.C { poll() }

Goroutines are a different world from Python’s GIL-constrained threads. If you work in both languages, my Python Threading & Concurrency Cheatsheet makes a handy side-by-side.

  • Python Threading & Concurrency is the contrast case: the GIL, ThreadPoolExecutor, and asyncio next to goroutines and channels
  • Docker has the multi-stage builds that shrink a Go binary into a scratch image, plus the run flags and compose reference
  • Kubernetes is where Go tooling lives in production: kubectl reference, manifest skeletons, rollouts, and debugging

There’s more in the Languages group, or start from the whole cheatsheet library.

Similar Articles

More from development

Bash Basics Cheatsheet

Quick-reference Bash basics cheatsheet: variables, parameter expansion, conditionals, loops, arrays, …

No related topic suggestions found.