# Golang Safety > Codificación defensiva en Golang para evitar panics, corrupción silenciosa de datos y bugs sutiles en tiempo de ejecución. Fuente: https://skillsagentes.com/skills/samber/cc-skills-golang/golang-safety Markdown: https://skillsagentes.com/skills/samber/cc-skills-golang/golang-safety.md Repositorio: https://github.com/samber/cc-skills-golang Autor: samber Licencia: MIT Actualizado: hace 2 meses Coste de contexto: 96 tok instalada, 2.6k tok al activarse, 17.3k tok con todos los archivos del bundle Bundle: 4 archivos, 68 KB Permisos que pide: read edit write glob grep bash(go:*) bash(golangci-lint:*) bash(git:*) agent ## Instalación Un skill son archivos markdown: los mismos archivos valen para cualquier agente y lo único que cambia es el directorio de destino, es decir la bandera `--agent`. Añade `-g` para instalarlo en todos los proyectos de la máquina. ```bash # Claude Code npx -y skills add samber/cc-skills-golang --skill golang-safety --agent claude-code # Cursor npx -y skills add samber/cc-skills-golang --skill golang-safety --agent cursor # Codex npx -y skills add samber/cc-skills-golang --skill golang-safety --agent codex # Gemini CLI npx -y skills add samber/cc-skills-golang --skill golang-safety --agent gemini # Windsurf npx -y skills add samber/cc-skills-golang --skill golang-safety --agent windsurf # Cline npx -y skills add samber/cc-skills-golang --skill golang-safety --agent cline ``` ## Qué hace - Aplica prácticas defensivas de Go: nil-safety, aserciones de tipo seguras, prevención de aliasing en slices con append - Detecta y corrige truncamientos silenciosos en conversiones numéricas y comparaciones incorrectas de floats - Revisa manejo de recursos (defer en loops) y copias defensivas de slices/mapas exportados - Guía diseño de zero-values seguros y uso de sync.Once para inicialización perezosa ## Cuándo usarla - Al encontrar panics por nil, aliasing de append, acceso concurrente a mapas o problemas de comparación de floats - Al diseñar zero-values o revisar código para nil-safety - Al revisar overflow en conversiones numéricas o problemas de ciclo de vida de recursos (defer en loops) - Al revisar copia defensiva de slices y mapas ## Qué la activa - "Revisa este código Go por posibles nil panics" - "¿Por qué mi slice se corrompe después de usar append?" - "Ayúdame a diseñar zero-values seguros para esta struct" - "Revisa si hay overflow en estas conversiones de int64 a int32" ## Antes de instalar - Requiere el binario go instalado; opcionalmente golangci-lint y git. ## Archivos - SKILL.md — 10 KB - evals/evals.json — 47 KB - references/nil-safety.md — 5 KB - references/slice-map-safety.md — 5 KB ## SKILL.md Reproducido tal cual desde samber/cc-skills-golang bajo MIT. Esta sección es el documento original y está en inglés. **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: ```go // ✗ Dangerous — interface{type: *MyHandler, value: nil} is not == nil func getHandler() http.Handler { var h *MyHandler // nil pointer if !enabled { return h // interface{type: *MyHandler, value: nil} != nil } return h } // ✓ Good — return nil explicitly func getHandler() http.Handler { if !enabled { return nil // interface{type: nil, value: nil} == nil } return &MyHandler{} } ``` ### 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 | ```go // ✗ Bad — nil map panics on write var m map[string]int m["key"] = 1 // ✓ Good — initialize or lazy-init in methods m := make(map[string]int) func (r *Registry) Add(name string, val int) { if r.items == nil { r.items = make(map[string]int) } r.items[name] = val } ``` 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: ```go // ✗ Dangerous — a and b share backing array a := make([]int, 3, 5) b := append(a, 4) b[0] = 99 // also modifies a[0] // ✓ Good — full slice expression forces new allocation b := append(a[:len(a):len(a)], 4) ``` ### 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 ```go // ✗ Bad — silently wraps around if val > math.MaxInt32 (3B becomes -1.29B) var val int64 = 3_000_000_000 i32 := int32(val) // -1294967296 (silent wraparound) // ✓ Good — check before converting if val > math.MaxInt32 || val < math.MinInt32 { return fmt.Errorf("value %d overflows int32", val) } i32 := int32(val) ``` ### Float comparison ```go // ✗ Bad — floating point arithmetic is not exact var a, b, c float64 = 0.1, 0.2, 0.3 a+b == c // false // ✓ Good — use epsilon comparison const epsilon = 1e-9 math.Abs((a+b)-c) < epsilon // true ``` ### Division by zero Integer division by zero panics. Float division by zero produces `+Inf`, `-Inf`, or `NaN`. ```go func avg(total, count int) (int, error) { if count == 0 { return 0, errors.New("division by zero") } return total / count, nil } ``` 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: ```go // ✗ Bad — all files stay open until function returns for _, path := range paths { f, _ := os.Open(path) defer f.Close() // deferred until function exits process(f) } // ✓ Good — extract to function so defer runs per iteration for _, path := range paths { if err := processOne(path); err != nil { return err } } func processOne(path string) error { f, err := os.Open(path) if err != nil { return err } defer f.Close() return process(f) } ``` ### 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 ```go // ✗ Bad — exported slice field, anyone can mutate type Config struct { Hosts []string } // ✓ Good — unexported field with accessor returning a copy type Config struct { hosts []string } func (c *Config) Hosts() []string { return slices.Clone(c.hosts) } ``` ## Initialization Safety ### Zero-value design Design types so `var x MyType` is safe — prevents "forgot to initialize" bugs: ```go var mu sync.Mutex // ✓ usable at zero value var buf bytes.Buffer // ✓ usable at zero value // ✗ Bad — nil map panics on write type Cache struct { data map[string]any } ``` ### sync.Once for lazy initialization ```go type DB struct { once sync.Once conn *sql.DB } func (db *DB) connection() *sql.DB { db.once.Do(func() { db.conn, _ = sql.Open("postgres", connStr) }) return db.conn } ``` ### 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)`. ```go v := reflect.ValueOf(x) if s, ok := reflect.TypeAssert[string](v); ok { use(s) } ``` ## 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 ## 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-continuous-integration` skill for automated AI-driven code review in CI using these guidelines ## Dónde encaja - Categoría: [Testing y QA](https://skillsagentes.com/categorias/testing-qa.md) — Flujos de testing unitario, de integración y end-to-end. - Creador: [samber](https://skillsagentes.com/creators/samber.md) — 0 skills en el directorio - [Todas las skills](https://skillsagentes.com/skills.md) - [Ranking de instalaciones](https://skillsagentes.com/ranking.md) ## Otras skills del mismo repositorio - [Golang Lint](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-lint.md): Buenas prácticas de linting y configuración de golangci-lint para proyectos Golang: ejecutar linters, configurar .golangci.yml, suprimir avisos con nolint, interpretar salidas y elegir linters. - [Golang Benchmark](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-benchmark.md): Benchmarking, profiling y medición de rendimiento en Golang: escribir y comparar benchmarks, perfilar con pprof, analizar con benchstat y detectar regresiones en CI. - [Golang How To](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-how-to.md): Orquestador de skills de Golang, siempre activo en cualquier tarea de código, revisión, debug o setup: carga las skills más relevantes de samber/cc-skills-golang, a menudo varias a la vez. - [Golang Testing](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-testing.md): Tests de Golang listos para producción: table-driven, suites y mocks con testify, tests paralelos, fuzzing, fixtures, detección de fugas de goroutines con goleak, snapshot testing, cobertura, tests de integración. - [Golang Performance](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-performance.md): Patrones y metodología de optimización de rendimiento en Golang: si hay cuello de botella X, aplica el patrón Y, una vez que profiling o benchmarks ya lo identificaron. ## Skills relacionadas - [Golang Stretchr Testify](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-stretchr-testify.md): Guía completa de stretchr/testify para testing en Golang: assert, require, mock y suite, con matchers, verificación de llamadas y patrones avanzados como Eventually y JSONEq. - [Golang Testing](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-testing.md): Tests de Golang listos para producción: table-driven, suites y mocks con testify, tests paralelos, fuzzing, fixtures, detección de fugas de goroutines con goleak, snapshot testing, cobertura, tests de integración. - [Golang Troubleshooting](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-troubleshooting.md): Depura programas Go de forma sistemática hasta encontrar y corregir la causa raíz: metodología de debugging, errores comunes de Go, pprof, Delve, detección de races y depuración en producción. - [Golang Benchmark](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-benchmark.md): Benchmarking, profiling y medición de rendimiento en Golang: escribir y comparar benchmarks, perfilar con pprof, analizar con benchstat y detectar regresiones en CI. - [Golang Graphql](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-graphql.md): Implementa APIs GraphQL en Golang con gqlgen o graphql-go: diseño de schemas, resolvers, suscripciones e integración con servicios HTTP en Go. --- Skills Agentes · [Índice de páginas en markdown](https://skillsagentes.com/sitemap.md) · [Inicio](https://skillsagentes.com/index.md)