Skip to content

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

相关文档