Get the FREE Ultimate OpenClaw Setup Guide →

go-performance

Scanned
npx machina-cli add skill cxuu/golang-skills/go-performance --openclaw
Files (1)
SKILL.md
4.6 KB

Go Performance Patterns

Source: Uber Go Style Guide

Performance-specific guidelines apply only to the hot path. Don't prematurely optimize—focus these patterns where they matter most.


Prefer strconv over fmt

When converting primitives to/from strings, strconv is faster than fmt.

Source: Uber Go Style Guide

Bad:

for i := 0; i < b.N; i++ {
    s := fmt.Sprint(rand.Int())
}

Good:

for i := 0; i < b.N; i++ {
    s := strconv.Itoa(rand.Int())
}

Benchmark comparison:

ApproachSpeedAllocations
fmt.Sprint143 ns/op2 allocs/op
strconv.Itoa64.2 ns/op1 allocs/op

Avoid Repeated String-to-Byte Conversions

Do not create byte slices from a fixed string repeatedly. Instead, perform the conversion once and capture the result.

Source: Uber Go Style Guide

Bad:

for i := 0; i < b.N; i++ {
    w.Write([]byte("Hello world"))
}

Good:

data := []byte("Hello world")
for i := 0; i < b.N; i++ {
    w.Write(data)
}

Benchmark comparison:

ApproachSpeed
Repeated conversion22.2 ns/op
Single conversion3.25 ns/op

The good version is ~7x faster because it avoids allocating a new byte slice on each iteration.


Prefer Specifying Container Capacity

Specify container capacity where possible to allocate memory up front. This minimizes subsequent allocations from copying and resizing as elements are added.

Source: Uber Go Style Guide

Map Capacity Hints

Provide capacity hints when initializing maps with make().

make(map[T1]T2, hint)

Note: Unlike slices, map capacity hints do not guarantee complete preemptive allocation—they approximate the number of hashmap buckets required.

Bad:

files, _ := os.ReadDir("./files")

m := make(map[string]os.DirEntry)
for _, f := range files {
    m[f.Name()] = f
}
// Map resizes dynamically, causing multiple allocations

Good:

files, _ := os.ReadDir("./files")

m := make(map[string]os.DirEntry, len(files))
for _, f := range files {
    m[f.Name()] = f
}
// Map is right-sized at initialization, fewer allocations

Slice Capacity

Provide capacity hints when initializing slices with make(), particularly when appending.

make([]T, length, capacity)

Unlike maps, slice capacity is not a hint—the compiler allocates exactly that much memory. Subsequent append() operations incur zero allocations until capacity is reached.

Bad:

for n := 0; n < b.N; n++ {
    data := make([]int, 0)
    for k := 0; k < size; k++ {
        data = append(data, k)
    }
}

Good:

for n := 0; n < b.N; n++ {
    data := make([]int, 0, size)
    for k := 0; k < size; k++ {
        data = append(data, k)
    }
}

Benchmark comparison:

ApproachTime (100M iterations)
No capacity2.48s
With capacity0.21s

The good version is ~12x faster due to zero reallocations during append.


Pass Values

Source: Go Wiki CodeReviewComments (Advisory)

Don't pass pointers as function arguments just to save a few bytes. If a function refers to its argument x only as *x throughout, then the argument shouldn't be a pointer.

Common instances where values should be passed directly:

  • Pointer to a string (*string) — strings are already small fixed-size headers
  • Pointer to an interface value (*io.Reader) — interfaces are fixed-size (type + data pointers)

Bad:

func process(s *string) {
	fmt.Println(*s)  // only dereferences, never modifies
}

Good:

func process(s string) {
	fmt.Println(s)
}

Exceptions:

  • Large structs where copying is expensive
  • Small structs that might grow in the future

Quick Reference

PatternBadGoodImprovement
Int to stringfmt.Sprint(n)strconv.Itoa(n)~2x faster
Repeated []byte[]byte("str") in loopConvert once outside~7x faster
Map initializationmake(map[K]V)make(map[K]V, size)Fewer allocs
Slice initializationmake([]T, 0)make([]T, 0, cap)~12x faster
Small fixed-size args*string, *io.Readerstring, io.ReaderNo indirection

See Also

  • For core style principles: go-style-core
  • For naming conventions: go-naming

Source

git clone https://github.com/cxuu/golang-skills/blob/main/skills/go-performance/SKILL.mdView on GitHub

Overview

This skill distills practical Go performance patterns for hot paths. Learn when to optimize and how to speed string handling, conversions, and container allocations in performance critical sections.

How This Skill Works

Technically, apply these patterns in hot path code. Use strconv for primitive to string conversions, avoid repeated string to byte conversions by reusing a single data slice, and pre size maps and slices with make to minimize allocations. Favor passing values over pointers when the function only reads the argument, and profile to guide optimizations.

When to Use It

  • When converting primitives to strings in hot loops, use strconv instead of fmt.
  • When writing to buffers or IO inside tight loops where allocations are costly.
  • When building maps or slices in performance critical code; pre size with make.
  • When a function only reads its argument; pass by value rather than a pointer.
  • When profiling shows allocations dominating hot paths and you need concrete improvements.

Quick Start

  1. Step 1: Profile your code to identify hot paths.
  2. Step 2: Apply patterns like using strconv, reusing byte data, and pre sizing containers.
  3. Step 3: Re-run benchmarks and iterate on results.

Best Practices

  • Use strconv over fmt for primitive to string conversions.
  • Cache a single byte slice of fixed data and reuse it in loops.
  • Pre size maps and slices with make to reduce allocations.
  • Pass values by value when the function only reads them, avoid unnecessary pointers.
  • Profile first and optimize only hot paths to avoid premature optimization.

Example Use Cases

  • Converting ints to strings in a hot loop with strconv.Itoa
  • Reuse a precomputed []byte for repeated writes instead of converting each time
  • Initialize maps with capacity using make in batch loading
  • Pre size slices with make([]T,0,capacity) before appending
  • Pass strings by value rather than *string to avoid pointer indirection

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers