mcpField
G
go-service

go-service

github.com/brojonat开发139 次安装2 周前更新
代码仓库

关于 go-service

Go Service 是用于构建 Go 微服务的开发技能,面向采用标准库、SQL 和命令行工具的服务开发。内容涵盖依赖注入、HTTP 处理器、结构化日志、数据库代码生成和测试工作流。

主要功能

  1. 01使用标准库构建服务
  2. 02组合 HTTP 中间件
  3. 03显式传递依赖
  4. 04使用 slog 结构化日志
  5. 05通过 sqlc 生成类型安全代码
  6. 06构建可组合命令行界面

适用场景

  1. 01设计 Go 微服务结构
  2. 02实现 HTTP 处理器与中间件
  3. 03为 SQL 模式变更生成代码
  4. 04构建服务配套的 CLI

安装

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

$npx skills add https://github.com/brojonat/llmsrules --skill go-service

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

详细介绍

Go 服务

适用于生产环境的 Go 微服务,使用标准库、sqlc 编写 SQL、urfave/cli 处理命令,并使用 slog 进行结构化日志记录。

核心原则

  • 把一件事做好:每个组件只负责一项职责
  • 简单优于复杂:使用纯 JSON、标准 SQL 和环境变量
  • 组合:围绕管道和标准接口进行设计
  • 依赖显式传递:不使用全局变量或单例,通过参数传递所有内容

项目结构

.
├── cmd/
│   ├── server/          # Backend service entry point
│   └── client/          # CLI entry point
├── cli/                 # CLI implementation
├── client/              # Public client library
├── internal/            # Internal packages
│   └── db/             # Generated code (from sqlc)
├── migrations/          # SQL schema migrations
├── queries/             # SQL queries for sqlc
├── examples/            # Usage examples
├── testdata/            # Test fixtures
├── Makefile
├── .air.toml           # Air configuration
├── sqlc.yaml           # sqlc configuration
├── go.mod
├── README.md
└── CHANGELOG.md

处理函数模式

编写返回 http.Handler 的函数(遵循 Mat Ryer 的方法):

func handleListWallets(store TransactionStore, logger *slog.Logger) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ctx := r.Context()

        wallets, err := store.ListWallets(ctx)
        if err != nil {
            logger.ErrorContext(ctx, "failed to list wallets", "error", err)
            http.Error(w, "internal error", http.StatusInternalServerError)
            return
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(wallets)
    })
}

中间件组合

type adapter func(http.Handler) http.Handler

// adaptHandler applies adapters in reverse order so the first is outermost
func adaptHandler(h http.Handler, adapters ...adapter) http.Handler {
    for i := len(adapters) - 1; i >= 0; i-- {
        h = adapters[i](h)
    }
    return h
}

// Usage:
mux.Handle("GET /wallets", adaptHandler(
    handleListWallets(store, logger),
    withRequestID(),
    withLogging(logger),
    withMetrics(promRegistry),
    withJWTAuth(jwtSecret),
))

依赖注入

// Bad: hidden dependency on global
var db *sql.DB
func SaveTransaction(txn *Transaction) error {
    _, err := db.Exec("INSERT INTO transactions ...")
    return err
}

// Good: explicit dependencies
type TransactionStore interface {
    Save(ctx context.Context, txn *Transaction) error
}

type PostgresStore struct {
    db *sql.DB
}

func NewPostgresStore(db *sql.DB) *PostgresStore {
    return &PostgresStore{db: db}
}

// Dependencies are clear at construction time
store := NewPostgresStore(db)
poller := NewWalletPoller(solanaClient, store, natsConn)

使用 slog 进行结构化日志记录

func setupLogger(level slog.Level) *slog.Logger {
    opts := &slog.HandlerOptions{Level: level}
    return slog.New(slog.NewJSONHandler(os.Stderr, opts))
}

// Most logs at DEBUG level
logger.DebugContext(ctx, "polling wallet", "wallet", walletAddress, "last_slot", lastSlot)

// INFO for lifecycle events only
logger.InfoContext(ctx, "server started", "addr", addr, "version", version)

// ERROR for failures
logger.ErrorContext(ctx, "failed to store transaction", "error", err, "signature", sig)

通过 LOG_LEVEL 环境变量控制日志详细程度。生产环境默认为 WARN,开发环境默认为 DEBUG。

使用 sqlc 编写 SQL

编写 SQL,生成类型安全的 Go 代码:

# sqlc.yaml
version: "2"
sql:
  - engine: "postgresql"
    queries: "queries/"
    schema: "migrations/"
    gen:
      go:
        package: "db"
        out: "internal/db"

架构变更后务必重新生成代码,并提交生成的代码。

错误处理

// Always handle errors
txns, err := client.GetTransactions(ctx)
if err != nil {
    return fmt.Errorf("failed to get transactions: %w", err)
}

使用 urfave/cli 构建 CLI

构建简洁、可组合的命令行界面,支持自动绑定环境变量并提供内置帮助。

开发工作流

  1. 规划:先设计接口
  2. 先写测试(TDD):编写测试,编写最精简的代码,然后重构
  3. 服务端 + 客户端:每项服务端功能都配套一个客户端方法和一个 CLI 子命令
  4. Makefile:make test、make lint、make dev、make build-server
  5. 热重载:开发时使用 Air
  6. 代码检查:使用严格配置的 golangci-lint,修复所有警告

Unix 哲学

  • 默认保持静默:仅在发生错误或重要事件时输出
  • 标准输出使用 JSON:输出机器可读内容;为人类用户提供 --format=table|json|csv
  • 错误输出到标准错误:保持标准输出整洁,便于管道处理
  • 退出码:0 = 成功,非零 = 错误

评论

支持 Markdown