返回顶部
g

go-patternsGo语言模式

Go language patterns for 2026 — concurrency with errgroup, error wrapping, HTTP servers, gRPC, database access, testing, and CLI with Cobra

作者: admin | 来源: ClawHub
源自
ClawHub
版本
V 1.0.0
安全检测
已通过
333
下载量
免费
免费
0
收藏
概述
安装方式
版本历史

go-patterns

Go 语言模式与最佳实践

描述

面向 Go 1.24+ 的生产级 Go 模式,涵盖完整的开发生命周期。包括使用 errgroup 和 context 取消的惯用并发、使用 %w 的错误包装、使用 Chi 路由器的 HTTP 服务器、使用 pgx 的 PostgreSQL、gRPC 服务、表格驱动测试、使用 Cobra 的 CLI 工具以及使用 pprof 的性能分析。涵盖 Go 1.18+ 泛型、Go 1.22+ 整数范围迭代和 Go 1.23+ 迭代器。

使用方法

安装此技能以获取生产就绪的 Go 模式,包括:

  • - 所有 I/O 操作的 context.Context 传播
  • 用于安全管理并发 goroutine 的 errgroup
  • 使用 %w 和 errors.Is() / errors.As() 的错误包装
  • 标准项目布局(cmd/、internal/、pkg/)
  • 工作池、扇出/扇入和 select 多路复用

在 Go 项目开发中,此技能提供以下方面的上下文:

  • - 在 pgx、GORM 和 sqlc 之间选择数据库访问方式
  • 构建具有优雅关闭功能的 HTTP 服务器
  • 构建带有拦截器的 gRPC 服务
  • 防止 goroutine 泄漏和数据竞争
  • 在优化前使用 pprof 进行分析

关键模式

用于取消的 Context — I/O 操作必须使用

go
// 始终将 context 作为 I/O 函数的第一个参数
func FetchData(ctx context.Context, url string) ([]byte, error) {
req, err := http.NewRequestWithContext(ctx, GET, url, nil)
if err != nil { return nil, err }
resp, err := http.DefaultClient.Do(req)
if err != nil { return nil, err }
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}

// 调用者控制超时
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
data, err := FetchData(ctx, https://api.example.com/data)

用于并发任务的 errgroup

go
func ProcessItems(ctx context.Context, items []string) error {
g, ctx := errgroup.WithContext(ctx)
g.SetLimit(5) // 限制最多 5 个并发 goroutine

for _, item := range items {
item := item // 捕获循环变量
g.Go(func() error {
return processOne(ctx, item)
})
}
return g.Wait() // 返回第一个错误
}

错误包装

go
// 使用 %w 包装以保留错误链
func ReadConfig(path string) (Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return Config{}, fmt.Errorf(读取路径 %s 的配置: %w, path, err)
}
var cfg Config
if err := json.Unmarshal(data, &cfg); err != nil {
return Config{}, fmt.Errorf(解析配置: %w, err)
}
return cfg, nil
}

// errors.Is() 适用于包装的错误;== 不适用
if errors.Is(err, ErrNotFound) { ... }

// errors.As() 从链中提取自定义错误类型
var valErr *ValidationError
if errors.As(err, &valErr) {
fmt.Printf(无效字段: %s\n, valErr.Field)
}

标准项目布局

myapp/
├── cmd/myapp/main.go # 入口点
├── internal/
│ ├── domain/ # 业务逻辑(未导出)
│ ├── service/ # 应用服务
│ ├── repository/ # 数据访问层
│ └── http/ # HTTP 处理器
├── pkg/ # 公共库
├── migrations/ # SQL 迁移文件
└── go.mod

internal/ 由 Go 编译器强制执行。永远不要创建 /src。

Chi 路由器(推荐)

go
r := chi.NewRouter()
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(middleware.RequestID)

r.Get(/, homeHandler)
r.Post(/users, createUserHandler)
r.Route(/api, func(r chi.Router) {
r.Use(authMiddleware)
r.Get(/profile, getProfileHandler)
})
http.ListenAndServe(:8080, r)

优雅关闭

go
server := &http.Server{
Addr: :8080, Handler: setupRoutes(),
ReadTimeout: 5 time.Second, WriteTimeout: 5 time.Second,
}
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigChan
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
server.Shutdown(ctx)
}()
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf(服务器错误: %v, err)
}

pgx — 最佳 PostgreSQL 驱动

go
config, _ := pgxpool.ParseConfig(postgres://user:pass@localhost/db)
config.MaxConns = 25
pool, err := pgxpool.NewWithConfig(context.Background(), config)

var id int; var name string
err = pool.QueryRow(ctx, SELECT id, name FROM users WHERE id = $1, 1).Scan(&id, &name)
if errors.Is(err, pgx.ErrNoRows) { fmt.Println(未找到) }

数据库选择:pgx 用于高性能原始 SQL,GORM 用于复杂关系,sqlc 用于从 SQL 注释生成类型安全的 Go 代码。

表格驱动测试

go
func TestAdd(t *testing.T) {
tests := []struct{ name string; a, b, expected int }{
{正数, 2, 3, 5},
{负数, -2, -3, -5},
{零, 0, 0, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Add(tt.a, tt.b); got != tt.expected {
t.Errorf(Add(%d, %d) = %d, 期望 %d, tt.a, tt.b, got, tt.expected)
}
})
}
}

使用接口进行模拟

go
type Database interface {
GetUser(ctx context.Context, id int) (User, error)
}
// 注入接口,而非具体类型
type UserService struct { db Database }

// 用于测试的模拟
type MockDB struct{}
func (m *MockDB) GetUser(ctx context.Context, id int) (User, error) {
return User{ID: id, Name: 模拟用户}, nil
}

Cobra CLI

go
var rootCmd = &cobra.Command{Use: myapp, Short: 我的应用程序}
var counterCmd = &cobra.Command{
Use: count, Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
max, _ := cmd.Flags().GetInt(max)
fmt.Printf(计数到 %d\n, max)
return nil
},
}
func init() {
rootCmd.AddCommand(counterCmd)
counterCmd.Flags().IntP(max, m, 10, 最大计数)
}

性能提示

  • - 预分配切片:make([]T, 0, capacity) — 避免重复分配
  • 循环中的字符串拼接:使用 strings.Builder 而非 +(O(n) 对比 O(n^2))
  • 先分析:go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30

反模式

问题解决方案
Goroutine 泄漏(无法退出)在 goroutine 循环中添加 case <-ctx.Done(): return
range ch 永不退出
发送方完成后必须 close(ch) | | 并发 map 写入 | 使用 sync.RWMutex 保护或使用 sync.Map | | 循环中的 defer f.Close() | 将循环体包装在命名函数中 |

工具与参考

标签

skill ai

通过对话安装

该技能支持在以下平台通过对话安装:

OpenClaw WorkBuddy QClaw Kimi Claude

方式一:安装 SkillHub 和技能

帮我安装 SkillHub 和 go-patterns-1776210045 技能

方式二:设置 SkillHub 为优先技能安装源

设置 SkillHub 为我的优先技能安装源,然后帮我安装 go-patterns-1776210045 技能

通过命令行安装

skillhub install go-patterns-1776210045

下载

⬇ 下载 go-patterns v1.0.0(免费)

文件大小: 3.84 KB | 发布时间: 2026-4-15 11:30

v1.0.0 最新 2026-4-15 11:30
Initial release of go-patterns providing production-ready Go development patterns:

- Covers idiomatic concurrency (errgroup), context usage, advanced error handling, and standard project structure.
- Includes patterns for HTTP servers (Chi), PostgreSQL access (pgx), gRPC, testing (table-driven, mocking), and CLI tools (Cobra).
- Addresses Go 1.18+ generics, new range/iterator syntax, and performance profiling with pprof.
- Features practical anti-patterns with solutions, and links to key Go resources.
- Suitable for Go 1.24+ and modern backend development workflows.

Archiver·手机版·闲社网·闲社论坛·羊毛社区· 多链控股集团有限公司 · 苏ICP备2025199260号-1

Powered by Discuz! X5.0   © 2024-2025 闲社网·线报更新论坛·羊毛分享社区·http://xianshe.com

p2p_official_large
返回顶部