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