Go 语言以其简洁性和高效性著称,本文总结一些实用的最佳实践。
代码风格
使用 gofmt
始终使用 gofmt 格式化代码,保持一致的代码风格。
gofmt -w .
命名规范
- 包名:小写单词,避免下划线
- 变量:驼峰命名,首字母大写表示导出
- 接口:单方法接口通常以
er结尾
// Good
type Reader interface {
Read(p []byte) (n int, err error)
}
// 包级变量
var maxRetries = 3
// 导出变量
var MaxConnections = 100
错误处理
总是检查错误
// Bad
file, _ := os.Open("file.txt")
// Good
file, err := os.Open("file.txt")
if err != nil {
return fmt.Errorf("failed to open file: %w", err)
}
defer file.Close()
使用 errors.Is 和 errors.As
if errors.Is(err, os.ErrNotExist) {
// 处理文件不存在
}
var pathErr *os.PathError
if errors.As(err, &pathErr) {
fmt.Println(pathErr.Path)
}
并发安全
使用 sync 包
var (
mu sync.RWMutex
counter int
)
func increment() {
mu.Lock()
defer mu.Unlock()
counter++
}
func getCount() int {
mu.RLock()
defer mu.RUnlock()
return counter
}
使用 atomic 包
var counter int64
func increment() {
atomic.AddInt64(&counter, 1)
}
性能优化
预分配切片容量
// Bad - 多次扩容
var result []int
for i := 0; i < 1000; i++ {
result = append(result, i)
}
// Good - 一次分配
result := make([]int, 0, 1000)
for i := 0; i < 1000; i++ {
result = append(result, i)
}
使用 strings.Builder
// Bad
var s string
for i := 0; i < 1000; i++ {
s += "a"
}
// Good
var sb strings.Builder
for i := 0; i < 1000; i++ {
sb.WriteString("a")
}
result := sb.String()
测试
表驱动测试
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive", 1, 2, 3},
{"negative", -1, -2, -3},
{"zero", 0, 0, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := Add(tt.a, tt.b)
if result != tt.expected {
t.Errorf("Add(%d, %d) = %d; want %d",
tt.a, tt.b, result, tt.expected)
}
})
}
}
持续更新中...