К основному содержанию
скилл Claude Code CX Codex Cursor GitHub Copilot

golang-samber-oops — скилл для Claude Code: структурированная

Скилл добавляет в Claude Code, Cursor и другие IDE знание о samber/oops — библиотеке для структурированной обработки ошибок в Go с контекстом, стек-трейсами, кодами ошибок и сообщениями для пользователя.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add samber/cc-skills-golang --skill golang-samber-oops -a claude-code
Открыть на GitHub

Что делает golang-samber-oops

samber/oops заменяет стандартный подход к ошибкам в Go. Вместо того чтобы писать fmt.Errorf("connection failed"), вы собираете ошибку как объект: указываете домен (какой сервис), теги, код ошибки, контекст пользователя и данные через метод .With(). Все переменные данные — ID пользователя, значения из запроса, SQL-запросы — идут в атрибуты, а не в строку сообщения. Это позволяет APM-инструментам (Datadog, Sentry, Loki) правильно группировать ошибки по типу, а не по уникальным значениям.

Скилл учит агента вызывать методы цепочкой: .In("domain"), .Tags(...), .Code("error_slug"), .User(id, key, value), .With(key, value), .Public("message for user") и завершающий метод вроде .Errorf() или .Wrapf(err, format, args). Скилл покрывает типичные сценарии: обработку ошибок в слое БД, в HTTP-обработчиках, в сервисах, оборачивание существующих ошибок, восстановление после паники.

Для работы нужен Go (инструмент go в PATH) и понимание, как устроена ошибка в вашем коде — скилл подскажет, какие атрибуты добавить и какой код ошибки выбрать. Если в проекте уже импортируется github.com/samber/oops, скилл сразу найдёт эту библиотеку и предложит её использовать.

Какие задачи решает

  • добавить структурированный контекст к ошибкам без изменения их формата
  • разделить техническое сообщение об ошибке от сообщения пользователю
  • настроить логирование и трейсинг ошибок с кодами и атрибутами
  • захватить стек вызовов и информацию о запросе при ошибке
  • сделать группировку ошибок в APM корректной по типу, не по конкретным значениям

Примеры запросов агенту

  • Помоги обработать ошибку подключения к БД с контекстом пользователя и SQL-запросом
  • Добавь структурированные ошибки в обработчик POST /users с публичным сообщением
  • Оберни существующую ошибку в сервисе через oops с кодом и тегами

Как установить golang-samber-oops

1Через Skills CLI (Vercel)

npx skills add samber/cc-skills-golang --skill golang-samber-oops -a claude-code

2Вручную: положить файлы

~/.claude/skills/golang-samber-oops/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/golang-samber-oops/

Из того же набора38

Весь набор →
golang-code-style samber Скилл помогает писать понятный код на Go, разбирая правила длины строк, объявления переменных, управления потоком выполнения и комментариев. Пригодится при написании и ревью кода, обсуждении стилистики или установке стандартов проекта. Claude Code CX Codex Cursor +1 44 000установок golang-error-handling samber Скилл для идиоматичной обработки ошибок в Go: оборачивание с контекстом, проверка цепочек, структурированное логирование и интеграция с samber/oops. Применяется при создании, оборачивании, инспекции и логировании ошибок. Claude Code CX Codex Cursor +1 43 200установок golang-security samber Находит уязвимости в коде на Go, выстраивает аудит по STRIDE и DREAD и помогает закрывать инъекции, утечки секретов и ошибки в криптографии. Claude Code CX Codex Cursor +1 42 100установок golang-design-patterns samber Скилл подсказывает идиоматичные Go-паттерны для API, жизненного цикла ресурсов, graceful shutdown и архитектуры. Пригодится при проектировании и ревью кода. Claude Code CX Codex Cursor +1 41 900установок golang-performance samber Помогает находить и устранять узкие места в Go-коде: сокращает аллокации памяти, оптимизирует горячие циклы и проверяет результаты замеров. Claude Code CX Codex Cursor +1 41 800установок golang-concurrency samber Скилл задаёт правила для конкурентного кода на Go: жизненный цикл горутин, каналы и select, мьютексы, errgroup, singleflight, воркер-пулы и fan-out/fan-in пайплайны. Claude Code CX Codex Cursor +1 41 600установок golang-database samber Набор правил для работы с реляционными базами данных в Go через database/sql, sqlx и pgx. Помогает писать запросы без ORM и проверять утечки соединений. Claude Code CX Codex Cursor +1 40 700установок golang-naming samber Скилл задаёт правила имён в Go: пакеты, типы, ошибки, булевы поля и тесты. Пригодится при написании, ревью и рефакторинге кода. Claude Code CX Codex Cursor +1 40 700установок

Похожие

iii-engine-config iii-hq Помогает настроить движок iii через worker-compose.yaml или config.yaml. Задаёт порты, параметры RBAC через rbac-proxy, ограничения наблюдателей и хранилище конфигураций. Claude Code CX Codex Cursor +1 4 200установок stripe-integration Seth Hobson Скилл помогает подключить Stripe: Checkout, подписки, вебхуки, возвраты и сохранение способов оплаты. Пригодится для платёжных сценариев в веб- и мобильных приложениях. Claude Code CX Codex Cursor 13 404установок mcp-builder официальный anthropics Скилл проводит через создание MCP-сервера на TypeScript или Python: от изучения протокола до тестов и оценки качества. Claude Code Claude.ai 130 949установок google-agents-cli-adk-code официальный Google Скилл даёт примеры и справку по Agent Development Kit: агентам, инструментам, колбэкам, состоянию и графовым workflow. Нужен при написании кода. Claude Code CX Codex Cursor +1 511 400установок lark-im larksuite Скилл подключает Lark IM к агенту: он отправляет сообщения, ищет историю, управляет чатами и файлами. Подойдёт для задач вокруг командных коммуникаций. Claude Code CX Codex Cursor +1 472 300установок lark-event larksuite Слушает события Lark/Feishu и отдаёт их потоком NDJSON. Подходит для ботов, обработчиков сообщений и долгих подписчиков. Claude Code CX Codex Cursor +1 466 200установок caveman-discover JuliusBrussee Находит точки вызова LLM в репозитории и размечает их воркфлоу для Caveman Cloud, чтобы расходы на токены не сливались в одну общую кучу. Claude Code CX Codex Cursor +1 103 500установок migration JuliusBrussee Скилл задаёт правила безопасных миграций схем, данных и API с обязательным откатом. Пригодится при изменениях, где нельзя терять данные или ломать совместимость. Claude Code CX Codex Cursor +1 102 900установок

Вопросы о golang-samber-oops

Как установить golang-samber-oops в Claude Code?

Выполни команду npx skills add samber/cc-skills-golang --skill golang-samber-oops -a claude-code, затем открой ~/.claude/skills/golang-samber-oops/SKILL.md для проверки установки.

Что делает golang-samber-oops?

Скилл учит агента использовать библиотеку samber/oops для структурированной обработки ошибок в Go: добавлять контекст, атрибуты, коды, сообщения для пользователя и стек-трейсы через метод-цепочку .In(), .Tags(), .Code(), .With(), .Public() и завершающий .Errorf() или .Wrapf().

Нужна ли дополнительная подготовка перед использованием?

Нужен Go (команда go в PATH). Если проект уже импортирует github.com/samber/oops, скилл сразу её найдёт; если нет, агент предложит добавить зависимость через go get.

Исходный текст

SKILL.md · MIT
---
name: golang-samber-oops
description: "Structured error handling in Golang with samber/oops — error builders, stack traces, error codes, error context, error wrapping, error attributes, user-facing vs developer messages, panic recovery, and logger integration. Apply when using or adopting samber/oops, or when the codebase already imports github.com/samber/oops."
user-invocable: true
license: MIT
compatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang.
metadata:
  author: samber
  version: "1.2.1"
  openclaw:
    emoji: "💥"
    homepage: https://github.com/samber/cc-skills-golang
    requires:
      bins:
        - go
    install: []
    skill-library-version: "1.21.0"
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs Bash(godig:*) Bash(gopls:*) LSP mcp__gopls__*
paths:
  - "**/*.go"
---

**Persona:** You are a Go engineer who treats errors as structured data. Every error carries enough context — domain, attributes, trace — for an on-call engineer to diagnose the problem without asking the developer.

# samber/oops Structured Error Handling

**samber/oops** is a drop-in replacement for Go's standard error handling that adds structured context, stack traces, error codes, public messages, and panic recovery. Variable data goes in `.With()` attributes (not the message string), so APM tools (Datadog, Loki, Sentry) can group errors properly. Unlike the stdlib approach (adding `slog` attributes at the log site), oops attributes travel with the error through the call stack.

## Why use samber/oops

Standard Go errors lack context — you see `connection failed` but not which user triggered it, what query was running, or the full call stack. `samber/oops` provides:

- **Structured context** — key-value attributes on any error
- **Stack traces** — automatic call stack capture
- **Error codes** — machine-readable identifiers
- **Public messages** — user-safe messages separate from technical details
- **Low-cardinality messages** — variable data in `.With()` attributes, not the message string, so APM tools group errors properly

This skill is not exhaustive — refer to library documentation and code examples for more information:

- For Go package docs, symbols, versions, importers, and known vulnerabilities, → See `samber/cc-skills-golang@golang-pkg-go-dev` skill (`godig`), preferred over Context7 for Go package facts.
- To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See `samber/cc-skills-golang@golang-gopls` skill (`gopls`).
- Context7 remains a fallback for docs not indexed on pkg.go.dev.

## Core pattern: Error builder chain

All `oops` errors use a fluent builder pattern:

```go
err := oops.
    In("user-service").           // domain/feature
    Tags("database", "postgres").  // categorization
    Code("network_failure").       // machine-readable identifier
    User("user-123", "email", "[email protected]").  // user context
    With("query", query).          // custom attributes
    Errorf("failed to fetch user: %s", "timeout")
```

Terminal methods:

- `.Errorf(format, args...)` — create a new error
- `.Wrap(err)` — wrap an existing error
- `.Wrapf(err, format, args...)` — wrap with a message
- `.Join(err1, err2, ...)` — combine multiple errors
- `.Recover(fn)` / `.Recoverf(fn, format, args...)` — convert panic to error

### Error builder methods

| Methods | Use case |
| --- | --- |
| `.With("key", value)` | Add custom key-value attribute (lazy `func() any` values supported) |
| `.WithContext(ctx, "key1", "key2")` | Extract values from Go context into attributes (lazy values supported) |
| `.In("domain")` | Set the feature/service/domain |
| `.Tags("auth", "sql")` | Add categorization tags (query with `err.HasTag("tag")`) |
| `.Code("iam_authz_missing_permission")` | Set machine-readable error identifier/slug |
| `.Public("Could not fetch user.")` | Set user-safe message (separate from technical details) |
| `.Hint("Runbook: https://doc.acme.org/doc/abcd.md")` | Add debugging hint for developers |
| `.Owner("team/slack")` | Identify responsible team/owner |
| `.User(id, "k", "v")` | Add user identifier and attributes |
| `.Tenant(id, "k", "v")` | Add tenant/organization context and attributes |
| `.Trace(id)` | Add trace / correlation ID (default: ULID) |
| `.Span(id)` | Add span ID representing a unit of work/operation (default: ULID) |
| `.Time(t)` | Override error timestamp (default: `time.Now()`) |
| `.Since(t)` | Set duration based on time since `t` (exposed via `err.Duration()`) |
| `.Duration(d)` | Set explicit error duration |
| `.Request(req, includeBody)` | Attach `*http.Request` (optionally including body) |
| `.Response(res, includeBody)` | Attach `*http.Response` (optionally including body) |
| `oops.FromContext(ctx)` | Start from an `OopsErrorBuilder` stored in a Go context |

## Common scenarios

### Database/repository layer

```go
func (r *UserRepository) FetchUser(id string) (*User, error) {
    query := "SELECT * FROM users WHERE id = $1"
    row, err := r.db.Query(query, id)
    if err != nil {
        return nil, oops.
            In("user-repository").
            Tags("database", "postgres").
            With("query", query).
            With("user_id", id).
            Wrapf(err, "failed to fetch user from database")
    }
    // ...
}
```

### HTTP handler layer

```go
func (h *Handler) CreateUser(w http.ResponseWriter, r *http.Request) {
    userID := getUserID(r)

    err := h.service.CreateUser(r.Context(), userID)
    if err != nil {
        err = oops.
            In("http-handler").
            Tags("endpoint", "/users").
            Request(r, false).
            User(userID).
            Wrapf(err, "create user failed")
        http.Error(w, oops.GetPublic(err, "Internal server error"), http.StatusInternalServerError)
        return
    }

    w.WriteHeader(http.StatusCreated)
}
```

### Service layer with reusable builder

```go
func (s *UserService) CreateOrder(ctx context.Context, req CreateOrderRequest) error {
    builder := oops.
        In("order-service").
        Tags("orders", "checkout").
        Tenant(req.TenantID, "plan", req.Plan).
        User(req.UserID, "email", req.UserEmail)

    product, err := s.catalog.GetProduct(ctx, req.ProductID)
    if err != nil {
        return builder.
            With("product_id", req.ProductID).
            Wrapf(err, "product lookup failed")
    }

    if product.Stock < req.Quantity {
        return builder.
            Code("insufficient_stock").
            Public("Not enough items in stock.").
            With("requested", req.Quantity).
            With("available", product.Stock).
            Errorf("insufficient stock for product %s", req.ProductID)
    }

    return nil
}
```

## Error wrapping best practices

### DO: Wrap directly, no nil check needed

```go
// ✓ Good — Wrap returns nil if err is nil
return oops.Wrapf(err, "operation failed")

// ✗ Bad — unnecessary nil check
if err != nil {
    return oops.Wrapf(err, "operation failed")
}
return nil
```

### DO: Add context at each layer

Each architectural layer SHOULD add context via Wrap/Wrapf — at least once per package boundary (not necessarily at every function call).

```go
// ✓ Good — each layer adds relevant context
func Controller() error {
    return oops.In("controller").Trace(traceID).Wrapf(Service(), "user request failed")
}

func Service() error {
    return oops.In("service").With("op", "create_user").Wrapf(Repository(), "db operation failed")
}

func Repository() error {
    return oops.In("repository").Tags("database", "postgres").Errorf("connection timeout")
}
```

### DO: Keep error messages low-cardinality

Error messages MUST be low-cardinality for APM aggregation. Interpolating variable data into the message breaks grouping in Datadog, Loki, Sentry.

```go
// ✗ Bad — high-cardinality, breaks APM grouping
oops.Errorf("failed to process user %s in tenant %s", userID, tenantID)

// ✓ Good — static message + structured attributes
oops.With("user_id", userID).With("tenant_id", tenantID).Errorf("failed to process user")
```

## Panic recovery

`oops.Recover()` MUST be used in goroutine boundaries. Convert panics to structured errors:

```go
func ProcessData(data string) (err error) {
    return oops.
        In("data-processor").
        Code("panic_recovered").
        Hint("Check input data format and dependencies").
        With("input_data", data).
        Recover(func() {
            riskyOperation(data)
        })
}
```

## Accessing error information

`samber/oops` errors implement the standard `error` interface. Access additional info:

```go
if oopsErr, ok := err.(oops.OopsError); ok {
    fmt.Println("Code:", oopsErr.Code())
    fmt.Println("Domain:", oopsErr.Domain())
    fmt.Println("Tags:", oopsErr.Tags())
    fmt.Println("Context:", oopsErr.Context())
    fmt.Println("Stacktrace:", oopsErr.Stacktrace())
}

// Get public-facing message with fallback
publicMsg := oops.GetPublic(err, "Something went wrong")
```

### Output formats

```go
fmt.Printf("%+v\n", err)       // verbose with stack trace
bytes, _ := json.Marshal(err)  // JSON for logging
slog.Error(err.Error(), slog.Any("error", err))  // slog integration
```

## Context propagation

Carry error context through Go contexts:

```go
func middleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        builder := oops.
            In("http").
            Request(r, false).
            Trace(r.Header.Get("X-Trace-ID"))

        ctx := oops.WithBuilder(r.Context(), builder)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

func handler(ctx context.Context) error {
    return oops.FromContext(ctx).Tags("handler", "users").Errorf("something failed")
}
```

For assertions, configuration, and additional logger examples, see [Advanced patterns](./references/advanced.md).

## References

- [github.com/samber/oops](https://github.com/samber/oops)
- [pkg.go.dev/github.com/samber/oops](https://pkg.go.dev/github.com/samber/oops)

## Cross-References

- → See `samber/cc-skills-golang@golang-error-handling` skill for general error handling patterns
- → See `samber/cc-skills-golang@golang-observability` skill for logger integration and structured logging

© samber · MIT · samber/cc-skills-golang

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой