← 返回 Skills 市场
samber

Golang Safety

作者 Samuel Berthe · GitHub ↗ · v1.1.1 · MIT-0
cross-platform ✓ 安全检测通过
146
总下载
0
收藏
0
当前安装
2
版本数
在 OpenClaw 中安装
/install golang-safety
功能描述
Defensive Golang coding to prevent panics, silent data corruption, and subtle runtime bugs. Use whenever writing or reviewing Go code that involves nil-prone...
使用说明 (SKILL.md)

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 comma-ok for type assertions — bare assertions panic on mismatch
  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 silentlyint64 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:

// ✗ 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 Read from nil Write to nil Len/Cap of nil Range over nil
Map Zero value panic 0 0 iterations
Slice panic (index) panic (index) 0 0 iterations
Channel Blocks forever Blocks forever 0 Blocks forever
// ✗ 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 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:

// ✗ 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 for range pitfalls, subslice memory retention, and slices.Clone/maps.Clone.

Numeric Safety

Implicit type conversions truncate silently

// ✗ 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 \x3C math.MinInt32 {
    return fmt.Errorf("value %d overflows int32", val)
}
i32 := int32(val)

Float comparison

// ✗ Bad — floating point arithmetic is not exact
0.1+0.2 == 0.3 // false

// ✓ Good — use epsilon comparison
const epsilon = 1e-9
math.Abs((0.1+0.2)-0.3) \x3C epsilon // true

Division by zero

Integer division by zero panics. Float division by zero produces +Inf, -Inf, or NaN.

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:

// ✗ 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

// ✗ 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:

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

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-linter skill for configuration and usage.

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) \x3C 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
安全使用建议
This skill is an instruction-only Go safety guide and is internally consistent with its stated purpose. Before installing, review the SKILL.md and reference files yourself to ensure the recommendations match your code style. Note the skill has access to run 'go' (and the tool permissions list includes bash wrappers like golangci-lint/git); if you permit autonomous invocation, the agent could run those tools against repositories the agent can access. If you want stricter control, keep autonomous invocation disabled or restrict the agent's repo/file access and review any commands it proposes before execution. Finally, verify the homepage/source if you need provenance beyond the provided docs.
功能分析
Type: OpenClaw Skill Name: golang-safety Version: 1.1.1 The 'golang-safety' skill bundle is a comprehensive set of defensive coding guidelines and evaluation cases designed to help an AI agent write safer Go code. It correctly identifies and provides mitigations for common Go pitfalls such as the nil interface trap, slice aliasing, integer truncation, and resource leaks in loops (found in SKILL.md and the references/ directory). The evaluation cases in evals/evals.json are high-quality tests for ensuring the agent avoids these vulnerabilities, and there is no evidence of malicious intent, prompt injection, or unauthorized data access.
能力评估
Purpose & Capability
Name/description are about defensive Go coding and the only declared runtime requirement is the 'go' binary; that is proportionate (linting, running examples/tests) and coherent with the skill's purpose.
Instruction Scope
SKILL.md contains coding guidance, examples, and deep-dive references about nil, slices, maps, numeric conversions, and resource lifecycles; it does not instruct reading unrelated system files, exfiltrating data, or using credentials. Examples and evaluation prompts are internal to Go coding checks.
Install Mechanism
There is no install spec and no code is written to disk by the skill itself (instruction-only), which minimizes install risk.
Credentials
No environment variables, credentials, or config paths are requested. The declared binary requirement ('go') is appropriate for a Go safety skill.
Persistence & Privilege
always is false and the skill does not request persistent or elevated privileges. The skill is allowed to be invoked autonomously (platform default), but it does not assert permanent presence or modify other skills.
如何使用
  1. 确保已安装 OpenClaw(本地或 Docker 部署)
  2. 在对话框中输入安装命令:/install golang-safety
  3. 安装完成后,直接呼叫该 Skill 的名称或使用 /golang-safety 触发
  4. 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
版本历史
v1.1.1
- Bumped version to 1.1.1 in metadata. - Added a new evaluation config file: evals/evals.json.
v0.1.0
- Initial release of the "golang-safety" skill focused on defensive Go coding. - Provides best practices for avoiding panics, silent data corruption, and subtle runtime bugs in Go projects. - Covers key safety topics: nil handling, slice and map aliasing, numeric conversions, resource lifecycle management, and defensive copying. - Includes practical examples and explanations for common pitfalls with pointers, interfaces, maps, slices, channels, type assertions, and zero-value design. - Offers linter recommendations and cross-references to related skills for concurrency, error handling, and security.
元数据
Slug golang-safety
版本 1.1.1
许可证 MIT-0
累计安装 0
当前安装数 0
历史版本数 2
常见问题

Golang Safety 是什么?

Defensive Golang coding to prevent panics, silent data corruption, and subtle runtime bugs. Use whenever writing or reviewing Go code that involves nil-prone... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 146 次。

如何安装 Golang Safety?

在 OpenClaw 或 Claude Code 对话框中运行命令「/install golang-safety」即可一键安装,无需额外配置。

Golang Safety 是免费的吗?

是的,Golang Safety 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。

Golang Safety 支持哪些平台?

Golang Safety 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。

谁开发了 Golang Safety?

由 Samuel Berthe(@samber)开发并维护,当前版本 v1.1.1。

💬 留言讨论