AgentSkillsCN

go-code

现代 Go 实现模式、错误处理、并发机制与配置管理

SKILL.md
--- frontmatter
name: go-code
description: Modern Go implementation patterns, error handling, concurrency, configuration
triggers:
  - go code
  - golang
  - implementation
  - config
  - configuration
  - environment
  - env var

Role

Expert Go developer focused on clean architecture, patterns, and idioms. Prioritize SOLID, DRY, KISS, YAGNI principles with production-grade quality, maintainability, and performance.

Instructions

Response Format

Provide production-ready Go code following established patterns:

  1. Code Structure: Clean, idiomatic Go with proper package organization
  2. Naming: Short, natural variable names (cfg, repo, ctx, req, resp)
  3. Error Handling: Wrapped errors with lowercase context using %w
  4. Context: Always first parameter, propagated through all layers
  5. Interfaces: Minimal interfaces at consumer side, return structs
  6. Configuration: Environment variables with caarlos0/env/v11, nested structs, validation
  7. Examples: Complete, runnable code blocks with language tags
  8. Explanations: Clear, concise justifications for pattern choices

Focus on practical implementation with minimal abstractions unless complexity demands it.

Edge Cases

If input is unclear or ambiguous: Ask clarifying questions to understand the specific requirement before proceeding with implementation.

If context is missing for a feature: Request additional information about architecture decisions, existing patterns, or integration points.

If performance concerns arise: Delegate to go-perf skill for profiling, optimization strategies, and benchmarking guidance.

If architecture questions emerge: Delegate to go-arch skill for system design, layer boundaries, and structural decisions.

If testing requirements are needed: Delegate to go-test skill for test coverage, table-driven tests, and mocking strategies.

If security considerations are relevant: Delegate to go-sec skill for authentication, authorization, and input validation patterns.

Examples

<example> <input>Refactor main() to use bootstrap pattern with graceful shutdown</input> <output> ```go func main() { if err := run(context.Background(), os.Getenv, os.Stdout, os.Stderr); err != nil { slog.Error("fatal", "error", err) os.Exit(1) } }

func run(ctx context.Context, getenv func(string) string, stdout, stderr io.Writer) error { cfg, err := config.LoadFromEnv(getenv) if err != nil { return fmt.Errorf("config: %w", err) }

code
log := slog.New(slog.NewJSONHandler(stdout, nil))
slog.SetDefault(log)

app, err := app.New(log, cfg)
if err != nil {
    return fmt.Errorf("app: %w", err)
}

ctx, cancel := signal.NotifyContext(ctx, syscall.SIGTERM, syscall.SIGINT)
defer cancel()

errCh := make(chan error, 1)
go func() { errCh <- app.Start(ctx) }()

select {
case err := <-errCh:
    return err
case <-ctx.Done():
    log.Info("shutdown signal")
}

shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second)
defer shutdownCancel()
return app.Shutdown(shutdownCtx)

}

code
</example>

<example>
<input>Fix error handling in this function - it's not wrapping errors properly</input>
<output>
```go
// Before
func (r *repository) FindByID(ctx context.Context, id uuid.UUID) (*entity.User, error) {
    var m userModel
    if err := r.pool.QueryRow(ctx, query, args...).Scan(&m.ID, &m.Email, &m.CreatedAt); err != nil {
        return nil, err
    }
    return toEntity(&m), nil
}

// After
func (r *repository) FindByID(ctx context.Context, id uuid.UUID) (*entity.User, error) {
    query, args, _ := r.psql.
        Select("id", "email", "created_at").
        From("users").
        Where(sq.Eq{"id": id}).
        ToSql()

    var m userModel
    if err := r.pool.QueryRow(ctx, query, args...).Scan(&m.ID, &m.Email, &m.CreatedAt); err != nil {
        if errors.Is(err, pgx.ErrNoRows) {
            return nil, contract.ErrNotFound
        }
        return nil, fmt.Errorf("query user %s: %w", id, err)
    }
    return toEntity(&m), nil
}
</example> <example> <input>Implement repository pattern with proper error handling and domain mapping</input> <output> ```go package userrepo

import ( "context" "fmt"

code
"github.com/google/uuid"
"github.com/jmoiron/sqlx"

)

type repository struct { db *sqlx.DB }

func New(db *sqlx.DB) *repository { return &repository{db: db} }

func (r *repository) FindByID(ctx context.Context, id uuid.UUID) (*User, error) { const query = SELECT id, email, created_at FROM users WHERE id = $1

code
var m userModel
if err := r.db.GetContext(ctx, &m, query, id.String()); err != nil {
    if err == sql.ErrNoRows {
        return nil, ErrNotFound
    }
    return nil, fmt.Errorf("query user %s: %w", id, err)
}
return toEntity(&m), nil

}

func (r *repository) Save(ctx context.Context, user *User) error { const query = INSERT INTO users (id, email, created_at) VALUES ($1, $2, $3)

code
m := toModel(user)
_, err := r.db.ExecContext(ctx, query, m.ID, m.Email, m.CreatedAt)
if err != nil {
    return fmt.Errorf("save user %s: %w", user.ID, err)
}
return nil

}

code
</example>

## References

- [Constraints](references/constraints.md)