A faster version is not automatically a better version. Keep code correct, clear, and concise first; optimize a path when its speed or efficiency matters. Identify the bottleneck before changing it, then check whether the change actually helps. Optimization can also target goals other than speed, such as floating-point accuracy. section 12.0 section 1.3.6
Common Go opportunities depend on the cause of the cost:
- Reduce heap allocations: use strings.Builder for suitable concatenation, avoid unnecessary []byte-to-string conversions, preallocate slices and maps when their sizes are known, and consider struct alignment. section 12.6
- Consider parallel execution when it is poorly structured, rather than assuming more concurrency will improve performance. section 1.3.6
- Check whether function structure permits inlining; a complex slow path can prevent a frequently used fast path from being inlined. section 12.7
A benchmark that measures an empty loop
A benchmark calling popcnt(uint64(i)) without using its result reported 0.2858 ns/op. The compiler could inline the call and remove the side-effect-free work. Keep each result in a benchmark-local variable, then assign the final result to a global variable after the loop. That version reported 1.993 ns/op; writing to the global on every iteration would add avoidable benchmark overhead. section 11.8.3
Similar map lookups, different generated code
When a map has string keys but the lookup input is []byte, storing string(bytes) in a local key before lookup differs from writing m[string(bytes)] directly. The Go compiler has a specific optimization for the direct lookup that avoids the bytes-to-string conversion. Check generated behavior rather than assuming similar-looking source has the same cost. section 12.6.2
func (m *Mutex) Lock() {
if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) {
if race.Enabled {
race.Acquire(unsafe.Pointer(m))
}
return
}
m.lockSlow() #1
}
func (m *Mutex) lockSlow() {
var waitStartTime int64
starving := false
awoke := false
iter := 0
old := m.state
for {
// ...
}
if race.Enabled {
race.Acquire(unsafe.Pointer(m))
}
}
The refactored Mutex.Lock keeps the fast path in a small function and moves the complex slow path into lockSlow. This makes inlining the fast-path call possible under the compiler’s complexity budget. section 12.7






