mcpField
G
go-best-practices

go-best-practices

github.com/alleneubank开发50359 次安装18 周前更新
代码仓库

关于 go-best-practices

go-best-practices 是面向 Go 的语言编码技能,依据 CLAUDE.md 中的类型优先、函数式和错误处理模式。内容包括状态建模、接口、错误链及结构化日志。

主要功能

  1. 01用自定义类型表示领域值
  2. 02通过接口定义行为约定
  3. 03采用函数选项和组合
  4. 04包装错误并保留错误链
  5. 05使用 log/slog 进行结构化日志记录

适用场景

  1. 01用不同类型建模领域 ID
  2. 02为依赖设计接口
  3. 03在调用链中保留错误上下文
  4. 04添加键值形式的结构化日志

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/alleneubank/claude-code --skill go-best-practices

安装后在 Claude Code 中输入/go-best-practices确认已加载。

详细介绍

Go 最佳实践

遵循 CLAUDE.md 中的类型优先、函数式和错误处理模式。本技能仅涵盖语言特有的惯用写法。

让非法状态无法表示

使用 Go 的类型系统在编译时防止无效状态。

为领域基础类型定义自定义类型:

// Distinct types prevent mixing up IDs
type UserID string
type OrderID string

func GetUser(id UserID) (*User, error) {
    // Compiler prevents passing OrderID here
}

// Methods attach behavior to the type
func (id UserID) String() string {
    return string(id)
}

使用接口定义行为契约:

// Define what you need, not what you have
type UserRepository interface {
    GetByID(ctx context.Context, id UserID) (*User, error)
    Save(ctx context.Context, user *User) error
}

// Accept interfaces, return structs
func ProcessInput(r io.Reader) ([]byte, error) {
    return io.ReadAll(r)
}

使用 iota 定义枚举,并确保 switch 覆盖所有情况:

type Status int

const (
    StatusActive Status = iota + 1
    StatusInactive
    StatusPending
)

func ProcessStatus(s Status) (string, error) {
    switch s {
    case StatusActive:
        return "processing", nil
    case StatusInactive:
        return "skipped", nil
    case StatusPending:
        return "waiting", nil
    default:
        return "", fmt.Errorf("unhandled status: %v", s)
    }
}

使用函数选项实现灵活构造:

type ServerOption func(*Server)

func WithPort(port int) ServerOption {
    return func(s *Server) { s.port = port }
}

func NewServer(opts ...ServerOption) *Server {
    s := &Server{port: 8080, timeout: 30 * time.Second}
    for _, opt := range opts {
        opt(s)
    }
    return s
}
// Usage: NewServer(WithPort(3000), WithTimeout(time.Minute))

使用嵌入实现组合:

type Timestamps struct {
    CreatedAt time.Time
    UpdatedAt time.Time
}

type User struct {
    Timestamps  // User gains CreatedAt, UpdatedAt
    ID    UserID
    Email string
}

Go 特有的错误处理

使用 %w 包装错误,以便通过 errors.Is / errors.As 保留错误链:

out, err := client.Do(ctx, req)
if err != nil {
    return nil, fmt.Errorf("fetch widget failed: %w", err)
}

结构化日志记录

使用 log/slog 和结构化键值对:

import "log/slog"

var log = slog.With("component", "widgets")

func createWidget(name string) (*Widget, error) {
    log.Debug("creating widget", "name", name)
    widget := &Widget{Name: name}
    log.Debug("created widget", "id", widget.ID)
    return widget, nil
}

评论

支持 Markdown