go-dev

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Go 开发规范

Go Development Guidelines

参考来源: Effective Go、Go Code Review Comments、uber-go/guide

Reference Sources: Effective Go, Go Code Review Comments, uber-go/guide

工具链

Toolchain

bash
goimports -w .                    # 格式化并整理 import
go vet ./...                      # 静态分析
golangci-lint run                 # 综合检查
go test -v -race -cover ./...     # 测试(含竞态检测和覆盖率)

bash
goimports -w .                    # Format and organize imports
go vet ./...                      # Static analysis
golangci-lint run                 # Comprehensive check
go test -v -race -cover ./...     # Testing (including race detection and coverage)

命名约定

Naming Conventions

类型规则示例
包名小写单词,不用下划线
user
,
orderservice
变量/函数驼峰命名,缩写词一致大小写
userID
,
HTTPServer
常量导出用驼峰,私有可驼峰或全大写
MaxRetryCount
接口单方法用方法名+er
Reader
,
Writer
禁止:
common
,
util
,
base
等无意义包名

TypeRuleExample
Package NameLowercase words, no underscores
user
,
orderservice
Variable/FunctionCamelCase, consistent case for abbreviations
userID
,
HTTPServer
ConstantExported ones use CamelCase, private ones can use CamelCase or all uppercase
MaxRetryCount
InterfaceSingle-method interfaces use method name + er
Reader
,
Writer
Prohibited: Meaningless package names like
common
,
util
,
base

import 顺序

Import Order

go
import (
    "context"           // 标准库
    "fmt"

    "github.com/gin-gonic/gin"  // 第三方库

    "project/internal/model"     // 项目内部
)

go
import (
    "context"           // Standard library
    "fmt"

    "github.com/gin-gonic/gin"  // Third-party libraries

    "project/internal/model"     // Internal project code
)

错误处理

Error Handling

必须处理错误,不能忽略:
go
// ✅ 好:添加上下文
if err != nil {
    return fmt.Errorf("failed to query user %d: %w", userID, err)
}

// ❌ 差:忽略错误
result, _ := doSomething()
错误包装: 使用
%w
保留错误链,用
errors.Is()
/
errors.As()
检查

Errors must be handled, cannot be ignored:
go
// ✅ Good: Add context
if err != nil {
    return fmt.Errorf("failed to query user %d: %w", userID, err)
}

// ❌ Bad: Ignore error
result, _ := doSomething()
Error Wrapping: Use
%w
to preserve error chain, use
errors.Is()
/
errors.As()
for checking

并发编程

Concurrent Programming

基本原则:
  • 优先使用 channel 通信
  • 启动 goroutine 前考虑:谁来等待它?怎么停止它?
  • 使用
    context.Context
    控制生命周期
go
// ✅ 好:使用 context 控制
func process(ctx context.Context) error {
    done := make(chan error, 1)
    go func() { done <- doWork() }()

    select {
    case err := <-done:
        return err
    case <-ctx.Done():
        return ctx.Err()
    }
}
数据竞争: 使用
go test -race
检测

Basic Principles:
  • Prioritize using channel communication
  • Before starting a goroutine, consider: Who will wait for it? How to stop it?
  • Use
    context.Context
    to control lifecycle
go
// ✅ Good: Control with context
func process(ctx context.Context) error {
    done := make(chan error, 1)
    go func() { done <- doWork() }()

    select {
    case err := <-done:
        return err
    case <-ctx.Done():
        return ctx.Err()
    }
}
Data Races: Use
go test -race
to detect

测试规范

Testing Specifications

go
// 表驱动测试
func TestAdd(t *testing.T) {
    tests := []struct {
        name     string
        a, b     int
        expected int
    }{
        {"positive", 1, 2, 3},
        {"zero", 0, 0, 0},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got := Add(tt.a, tt.b)
            if got != tt.expected {
                t.Errorf("Add(%d, %d) = %d, want %d", tt.a, tt.b, got, tt.expected)
            }
        })
    }
}

go
// Table-driven test
func TestAdd(t *testing.T) {
    tests := []struct {
        name     string
        a, b     int
        expected int
    }{
        {"positive", 1, 2, 3},
        {"zero", 0, 0, 0},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got := Add(tt.a, tt.b)
            if got != tt.expected {
                t.Errorf("Add(%d, %d) = %d, want %d", tt.a, tt.b, got, tt.expected)
            }
        })
    }
}

性能优化

Performance Optimization

陷阱解决方案
循环中拼接字符串使用
strings.Builder
未预分配 slice
make([]T, 0, cap)
N+1 查询批量查询 + 预加载
无限制并发使用 semaphore 或 worker pool
bash
undefined
PitfallSolution
String concatenation in loopsUse
strings.Builder
Unpreallocated slice
make([]T, 0, cap)
N+1 queriesBatch queries + preloading
Unbounded concurrencyUse semaphore or worker pool
bash
undefined

性能分析

Performance analysis

go test -cpuprofile=cpu.prof -bench=. go tool pprof cpu.prof

---
go test -cpuprofile=cpu.prof -bench=. go tool pprof cpu.prof

---

项目结构

Project Structure

project/
├── cmd/                    # 可执行文件入口
├── internal/               # 私有代码
│   ├── handler/
│   ├── service/
│   ├── repository/
│   └── model/
├── pkg/                    # 公共代码
├── go.mod
└── go.sum

project/
├── cmd/                    # Executable entry points
├── internal/               # Private code
│   ├── handler/
│   ├── service/
│   ├── repository/
│   └── model/
├── pkg/                    # Public code
├── go.mod
└── go.sum

详细参考

Detailed References

完整规范见
references/go-style.md
,包含:
  • 完整命名约定和示例
  • 详细错误处理模式
  • 并发编程最佳实践
  • 测试辅助函数写法
  • 性能优化工具使用

📋 本回复遵循:
go-dev
- [具体章节]
Complete guidelines can be found in
references/go-style.md
, including:
  • Complete naming conventions and examples
  • Detailed error handling patterns
  • Best practices for concurrent programming
  • Writing test helper functions
  • Usage of performance optimization tools

📋 This response follows:
go-dev
- [Specific Section]