golang-safety
Defensive Golang coding against accidental bugs — nil panics, typed-nil interfaces, `append` backing-array aliasing, silent int64-to-int32 truncation, float `==` comparison, `defer` inside loops, defensive copies of slices and maps, and usable zero values. Use when a Go program panics on a nil map w
By samber · 38,021 installs
npx skills add samber/cc-skills-golang --skill golang-safety
Source repository · Upstream listing
Persona: You are a defensive Go engineer. You treat every untested assumption about nil, capacity, and numeric range as a latent crash waiting to happen.
Go Safety: Correctness & Defensive Coding
Prevents programmer mistakes — bugs, panics, and silent data corruption in normal (non adversarial) code. Security handles attackers; safety handles ourselves.
Best Practices Summary
1. Prefer generics over any when the type set is known — compiler catches mismatches instead of runtime panics
2. Always use safe type assertions — for normal interfaces use comma ok ( v, ok := x.(T) ); for reflection in Go 1.25+ prefer reflect.TypeAssert[T](value) over value.Interface().(T) .
3. Typed nil pointer in an interface is not == nil — the type descriptor makes it non nil
4. Writing to a nil map panics — always initialize before use
5. append may reuse the backing array — both slices share memory if capacity allows, silently corrupting each other
6. Return defensive copies from exported functions — otherwise callers mutate your internals
7. defer runs at function exit, not loop iteration — extract loop body to a function
8. Integer conversions truncate silently — int64 to int32 wraps without error
9. Float arithmetic is not exact — use epsilon comparison or math/big
10. Design useful zero values — nil map fields panic on first write; use lazy init
11. Use sync.Once for lazy init — guarantees exactly once even under concurrency
Nil Safety
Nil related panics are the most common crash in Go.
The nil interface trap
Interfaces store (type, value). An interface is nil only when both are nil. Returning a typed nil pointer sets the type descriptor, making it non nil:
Nil map, slice, and channel behavior
Type Index into nil Write to nil Len/Cap of nil Range over nil
Map Zero value panic 0 0 iterations
Slice panic panic 0 0 iterations
Channel Blocks forever Blocks forever 0 Blocks forever
See [Nil Safety Deep Dive](./references/nil safety.md) for nil receivers, nil in generics, and nil interface performance.
Slice & Map Safety
Slice aliasing — the append trap
append reuses the backing array if capacity allows. Both slices then share memory:
Map concurrent access
Maps MUST NOT be accessed concurrently — → see samber/cc skills golang@golang concurrency for sync primitives.
See [Slice and Map Deep Dive](./references/slice map safety.md) for range pitfalls, subslice memory retention, and slices.Clone / maps.Clone .
Numeric Safety
Implicit type conversions truncate silently
Float comparison
Division by zero
Integer division by zero panics. Float division by zero produces +Inf , Inf , or NaN .
For integer overflow as a security vulnerability, see the samber/cc skills golang@golang security skill section.
Resource Safety
defer in loops — resource accumulation
defer runs at function exit, not loop iteration. Resources accumulate until the function returns:
Goroutine leaks
→ See samber/cc skills golang@golang concurrency for goroutine lifecycle and leak prevention.
Immutability & Defensive Copying
Exported functions returning slices/maps SHOULD return defensive copies.
Protecting struct internals
Initialization Safety
Zero value design
Design types so var x MyType is safe — prevents "forgot to initialize" bugs:
sync.Once for lazy initialization
init() function pitfalls
→ See samber/cc skills golang@golang design patterns for why init() should be avoided in favor of explicit constructors.
Enforce with Linters
Many safety pitfalls are caught automatically by linters: errcheck , forcetypeassert , nilerr , govet , staticcheck . See the samber/cc skills golang@golang lint skill for configuration and usage.
Go 1.25+ reflection type assertions
For reflection code, prefer reflect.TypeAssert[T] over value.Interface().(T) .
Common Mistakes
Mistake Fix
Bare type assertion v := x.(T) Panics on type mismatch, crashing the program. Use v, ok := x.(T) to handle gracefully
Returning typed nil in interface function Interface holds (type, nil) which is != nil. Return untyped nil for the nil case
Writing to a nil map Nil maps have no backing storage — write panics. Initialize with make(map[K]V) or lazy init
Assuming append always copies If capacity allows, both slices share the backing array. Use s[:len(s):len(s)] to force a copy
defer in a loop defer runs at function exit, not loop iteration — resources accumulate. Extract body to a separate function
int64 to int32 without bounds check Values wrap silently (3B → 1.29B). Check against math.MaxInt32 / math.MinInt32 first
Comparing floats with == IEEE 754 representation is not exact ( 0.1+0.2 != 0.3 ). Use math.Abs(a b) < epsilon
Integer division without zero check Integer division by zero panics. Guard with if divisor == 0 before dividing
Returning internal slice/map reference Callers can mutate your struct's internals through the shared backing array. Return a defensive copy
Multiple init() with ordering assumptions init() execution order across files is unspecified. → See samber/cc skills golang@golang design patterns — use explicit constructors
Blocking forever on nil channel Nil channels block on both send and receive. Always initialize before use
Cross References
→ See samber/cc skills golang@golang concurrency skill for concurrent access patterns and sync primitives
→ See samber/cc skills golang@golang data structures skill for slice/map internals, capacity growth, and container/ packages
→ See samber/cc skills golang@golang error handling skill for nil error interface trap
→ See samber/cc skills golang@golang security skill for security relevant safety issues (memory safety, integer overflow)
→ See samber/cc skills golang@golang troubleshooting skill for debugging panics and race conditions
→ See samber/cc skills golang@golang continuous integration skill for automated AI driven code review in CI using these guidelines