Go 语言规范
核心原则
Go 代码必须遵循官方代码规范,使用 gofmt 格式化,遵循 Effective Go 最佳实践。
允许的做法
包和导入
- 使用 小写单数形式命名包
- 使用 分组导入(标准库、第三方、本地)
go
// ✅ 正确
package handler
package service
package model
// ✅ 正确 - 分组导入
import (
"context"
"fmt"
"time"
"github.com/labstack/echo/v4"
"gorm.io/gorm"
"your-project/models"
"your-project/services"
)
// ❌ 错误
package handlers // 不使用复数
package myService // 不使用驼峰变量和常量
- 使用 camelCase 命名变量
- 使用 PascalCase 或 UPPER_SNAKE_CASE 命名常量
go
// ✅ 正确 - 变量
var userName string // 未导出
var UserCount int // 导出
// ✅ 正确 - 常量
const DefaultPageSize = 20
const MaxUploadSize = 10 * 1024 * 1024
// ✅ 正确 - 枚举常量(UPPER_SNAKE_CASE)
const (
STATUS_PENDING = "pending"
STATUS_IN_PROGRESS = "in_progress"
STATUS_COMPLETED = "completed"
)函数定义
- 使用 动词命名函数
- 使用 多返回值(值 + error)
go
// ✅ 正确
func GetUserByID(id int64) (*User, error) {
var user User
err := db.First(&user, id).Error
if err != nil {
return nil, err
}
return &user, nil
}
// ✅ 正确 - 命名返回值
func CreateOrder(userID int64, items []Item) (order *Order, err error) {
order = &Order{UserID: userID}
// ...
return
}错误处理
- 使用 error 返回值
- 使用 errors.New 或 fmt.Errorf 创建错误
- 使用 提前返回
go
// ✅ 正确 - 错误处理
func ProcessOrder(orderID int64) error {
order, err := orderRepo.FindByID(orderID)
if err != nil {
return fmt.Errorf("查询订单失败: %w", err)
}
if order.Status != "pending" {
return errors.New("订单状态不正确")
}
// 处理逻辑
return nil
}
// ✅ 正确 - 错误判断
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("记录不存在")
}
return fmt.Errorf("操作失败: %w", err)
}结构体定义
- 使用 PascalCase 导出结构体
- 使用 标签定义元数据
go
// ✅ 正确
type User struct {
ID int64 `json:"id" gorm:"column:id"`
Name string `json:"name" gorm:"column:name"`
Email string `json:"email" gorm:"column:email"`
CreatedAt int64 `json:"created_at" gorm:"column:created_at"`
}
func (User) TableName() string {
return "users"
}方法定义
- 使用 指针接收者(需要修改状态)
- 使用 值接收者(不修改状态)
- 使用 简短名称作为接收者
go
// ✅ 正确 - 指针接收者
func (u *User) SetName(name string) {
u.Name = name
}
func (s *UserService) Create(ctx context.Context, req *CreateUserRequest) (*User, error) {
// ...
}
// ✅ 正确 - 值接收者
func (u User) IsActive() bool {
return u.Status == "active"
}Context 使用
- 使用 context.Context 传递请求上下文
- 使用 context.WithTimeout 设置超时
go
// ✅ 正确
func GetUser(ctx context.Context, id int64) (*User, error) {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
var user User
err := db.WithContext(ctx).First(&user, id).Error
return &user, err
}禁止的做法
- 禁止 使用下划线命名
- 禁止 忽略 error
- 避免 panic(除非不可恢复的错误)
go
// ❌ 错误
var user_name string // 不使用下划线
user, _ := GetUser(id) // 忽略错误
panic("error") // 避免 panic
// ✅ 正确
var userName string
user, err := GetUser(id)
if err != nil {
return err
}最佳实践
零值可用
go
// ✅ 正确
var mu sync.Mutex
mu.Lock() // 零值可直接使用函数参数
- 避免 过多参数(超过 3 个使用结构体)
go
// ❌ 错误
func CreateUser(name, email, phone, addr string, age int) error
// ✅ 正确
type CreateUserRequest struct {
Name string
Email string
Phone string
Addr string
Age int
}
func CreateUser(req *CreateUserRequest) error