How do I…?

Task-oriented index. Each recipe is a real question paired with the smallest Go that answers it, and a link to the package it comes from. Use ⌘K to jump to one by name.

Strings & numbers

How do I Check if a string contains a substring?

if strings.Contains(s, "needle") {
    // ...
}

How do I Split on a separator?

For whitespace use strings.Fields.

parts := strings.Split("a,b,c", ",")
// []string{"a", "b", "c"}

How do I Join a slice of strings?

s := strings.Join([]string{"a", "b", "c"}, ", ")
// "a, b, c"

How do I Trim whitespace?

s = strings.TrimSpace(s)

How do I Build a long string efficiently?

strings.Builder avoids the O(n²) of repeated `s += ...`.

var b strings.Builder
for i := 0; i < 1000; i++ {
    fmt.Fprintf(&b, "row=%d ", i)
}
result := b.String()

How do I Convert a string to int?

n, err := strconv.Atoi("42")
if err != nil {
    return fmt.Errorf("parse count: %w", err)
}

How do I Convert int to string?

s := strconv.Itoa(42)
// "42"

How do I Format a float with N decimal places?

fmt
fmt.Sprintf("%.2f", 3.14159) // "3.14"

Files & I/O

How do I Read a whole file into memory?

os

Fine for small files. For huge files, stream with os.Open + bufio.

data, err := os.ReadFile("config.yaml")
if err != nil {
    return err
}

How do I Write a whole file (create or overwrite)?

os
err := os.WriteFile("out.txt", data, 0644)

How do I Read a file line by line?

f, err := os.Open("data.txt")
if err != nil {
    return err
}
defer f.Close()

sc := bufio.NewScanner(f)
for sc.Scan() {
    line := sc.Text()
    process(line)
}
if err := sc.Err(); err != nil {
    return err
}

How do I Check if a file exists?

_, err := os.Stat(path)
switch {
case err == nil:
    // exists
case errors.Is(err, fs.ErrNotExist):
    // does not exist
default:
    return err // some other error (permissions, I/O)
}

How do I Walk a directory tree?

err := filepath.WalkDir("dir", func(path string, d fs.DirEntry, err error) error {
    if err != nil {
        return err
    }
    if !d.IsDir() && strings.HasSuffix(path, ".go") {
        fmt.Println(path)
    }
    return nil
})

How do I Make a temp file or directory?

os
f, err := os.CreateTemp("", "myapp-*.json")
if err != nil {
    return err
}
defer os.Remove(f.Name())
defer f.Close()

dir, err := os.MkdirTemp("", "myapp-*")
defer os.RemoveAll(dir)

How do I Copy a stream from reader to writer?

io
_, err := io.Copy(dst, src)

How do I Read all stdin?

data, err := io.ReadAll(os.Stdin)

HTTP

How do I Make an HTTP GET?

http.DefaultClient has no timeout. For anything outside scripts, build your own &http.Client{Timeout: ...}.

resp, err := http.Get("https://example.com")
if err != nil {
    return err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)

How do I POST a JSON body?

body, _ := json.Marshal(payload)
resp, err := http.Post(url, "application/json", bytes.NewReader(body))
if err != nil {
    return err
}
defer resp.Body.Close()

How do I HTTP request with timeout and headers?

client := &http.Client{Timeout: 10 * time.Second}
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
    return err
}
req.Header.Set("Authorization", "Bearer "+token)
resp, err := client.Do(req)

How do I Tiny HTTP server?

Path patterns and PathValue are Go 1.22+.

mux := http.NewServeMux()
mux.HandleFunc("GET /hello/{name}", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "hello, %s\n", r.PathValue("name"))
})
log.Fatal(http.ListenAndServe(":8080", mux))

How do I Parse a URL and its query parameters?

u, err := url.Parse("https://api.x/?id=42&since=2026")
if err != nil {
    return err
}
id := u.Query().Get("id")

JSON

How do I Encode a struct to JSON bytes?

type User struct {
    Name string `json:"name"`
    Age  int    `json:"age,omitempty"`
}
b, err := json.Marshal(User{Name: "Ada", Age: 36})
// {"name":"Ada","age":36}

How do I Pretty-print JSON?

b, err := json.MarshalIndent(v, "", "  ")

How do I Decode JSON into a struct?

var u User
if err := json.Unmarshal(data, &u); err != nil {
    return err
}

How do I Decode arbitrary JSON?

var v any
if err := json.Unmarshal(data, &v); err != nil {
    return err
}
// v is map[string]any / []any / string / float64 / bool / nil

How do I Stream-decode JSON from an HTTP body?

Avoids loading the whole body into memory before parsing.

defer resp.Body.Close()
var u User
if err := json.NewDecoder(resp.Body).Decode(&u); err != nil {
    return err
}

Time

How do I Sleep for a duration?

time.Sleep(2 * time.Second)

How do I Time how long something takes?

start := time.Now()
doWork()
fmt.Println("took", time.Since(start))

How do I Format and parse RFC3339?

s := time.Now().Format(time.RFC3339)
t, err := time.Parse(time.RFC3339, s)

How do I Run a function on an interval?

tk := time.NewTicker(5 * time.Second)
defer tk.Stop()
for {
    select {
    case <-tk.C:
        beat()
    case <-ctx.Done():
        return
    }
}

Concurrency

How do I Wait for a group of goroutines?

Capture loop variables explicitly. (In Go 1.22+ this is no longer required, but explicit is still clearer.)

var wg sync.WaitGroup
for _, item := range items {
    wg.Add(1)
    go func(it Item) {
        defer wg.Done()
        process(it)
    }(item)
}
wg.Wait()

How do I Cancel work with context?

ctx, cancel := context.WithCancel(parent)
defer cancel()

go func() {
    if userPressedStop() {
        cancel()
    }
}()

select {
case result := <-doWork(ctx):
    use(result)
case <-ctx.Done():
    return ctx.Err()
}

How do I Run with a hard timeout?

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

req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
resp, err := http.DefaultClient.Do(req)

How do I Limit concurrency with a semaphore channel?

sem := make(chan struct{}, 8) // 8 in flight at once
for _, job := range jobs {
    sem <- struct{}{}
    go func(j Job) {
        defer func() { <-sem }()
        run(j)
    }(job)
}

How do I One-time lazy initialization?

var (
    once sync.Once
    db   *sql.DB
)
func getDB() *sql.DB {
    once.Do(func() { db = openDB() })
    return db
}

Slices & maps

How do I Sort a slice?

slices.Sort(nums)

How do I Sort a slice by a struct field?

slices.SortFunc(users, func(a, b User) int {
    return cmp.Compare(a.Age, b.Age)
})

How do I Deduplicate a slice?

Compact removes adjacent duplicates only; sort first.

slices.Sort(s)
s = slices.Compact(s)

How do I Get sorted keys of a map?

keys := make([]string, 0, len(m))
for k := range m {
    keys = append(keys, k)
}
slices.Sort(keys)

How do I Iterate a map in key order?

Go 1.23+ — uses iter.Seq from maps.Keys.

for _, k := range slices.Sorted(maps.Keys(m)) {
    fmt.Println(k, m[k])
}

Errors

How do I Wrap an error with context?

if err := load(id); err != nil {
    return fmt.Errorf("load user %s: %w", id, err)
}

How do I Check for a sentinel error?

var ErrNoUser = errors.New("no user")

if errors.Is(err, ErrNoUser) {
    // 404 path
}

How do I Extract a typed error?

var pe *fs.PathError
if errors.As(err, &pe) {
    log.Printf("path %q failed: %v", pe.Path, pe.Err)
}

CLI & runtime

How do I Parse command-line flags?

port := flag.Int("port", 8080, "listen port")
verbose := flag.Bool("v", false, "verbose")
flag.Parse()
fmt.Println(*port, *verbose, flag.Args())

How do I Get an env var with a default?

port := os.Getenv("PORT")
if port == "" {
    port = "8080"
}
// or, Go 1.22+:
port = cmp.Or(os.Getenv("PORT"), "8080")

How do I Catch ctrl-C cleanly?

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()

// pass ctx into your work; <-ctx.Done() fires on ^C

How do I Exit with a non-zero status?

os.Exit skips deferred functions; prefer returning errors from main.

if err := run(); err != nil {
    fmt.Fprintln(os.Stderr, err)
    os.Exit(1)
}

Hashing & crypto

How do I SHA-256 a string or bytes?

sum := sha256.Sum256([]byte("hello"))
hex := hex.EncodeToString(sum[:])

How do I Generate cryptographically random bytes?

crypto/rand, never math/rand, for anything that protects secrets.

buf := make([]byte, 32)
if _, err := rand.Read(buf); err != nil {
    return err
}

How do I Random integer for non-security purposes?

Go 1.22+ math/rand/v2 — auto-seeded, no Seed call needed.

n := rand.IntN(100) // 0..99

Testing

How do I Write a unit test?

func TestAdd(t *testing.T) {
    got := add(1, 2)
    if got != 3 {
        t.Fatalf("add(1,2) = %d, want 3", got)
    }
}

How do I Table-driven test?

func TestAdd(t *testing.T) {
    cases := []struct {
        name string
        a, b int
        want int
    }{
        {"zero", 0, 0, 0},
        {"pos", 2, 3, 5},
        {"neg", -1, 1, 0},
    }
    for _, c := range cases {
        t.Run(c.name, func(t *testing.T) {
            if got := add(c.a, c.b); got != c.want {
                t.Fatalf("add(%d,%d) = %d, want %d", c.a, c.b, got, c.want)
            }
        })
    }
}

Logging

How do I Structured log line with slog?

Default handler writes text. For JSON: slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stderr, nil))).

slog.Info("request",
    "method", r.Method,
    "path", r.URL.Path,
    "status", code,
    "ms", elapsed.Milliseconds(),
)