--- name: comment-standards description: Go 注释规范。编写 Go 代码注释、文档注释时使用。包含包注释、结构体注释、接口注释、函数注释、内联注释的完整规范与示例。 --- # Go 注释规范 **基本原则**: - **所有注释使用中文** - **导出符号必须有文档注释**(包、函数、方法、类型、接口、常量、变量) - **复杂逻辑必须有实现注释**(解释"为什么",而不是"做了什么") - **禁止废话注释**(不要用注释复述代码本身) - **修改代码时必须同步更新注释** --- ## 包注释 每个包的入口文件(通常是主文件或 `doc.go`)必须有包注释: ```go // Package account 提供账号管理的业务逻辑服务 // 包含账号创建、修改、删除、权限分配等功能 package account ``` ## 结构体注释 所有导出结构体必须有文档注释,说明该结构体代表什么: ```go // Service 账号业务服务 // 负责账号的 CRUD、角色分配、密码管理等业务逻辑 type Service struct { store *Store auditService AuditServiceInterface } ``` ## 接口注释 导出接口必须注释接口用途,每个方法必须说明契约: ```go // PermissionChecker 权限检查器接口 // 用于查询用户的权限列表 type PermissionChecker interface { // CheckPermission 检查用户是否拥有指定权限 // userID: 用户ID // permCode: 权限编码(格式: module:action) // platform: 端口类型 (all/web/h5) CheckPermission(ctx context.Context, userID uint, permCode string, platform string) (bool, error) } ``` ## 函数和方法注释 **导出函数/方法**必须以函数名开头,说明功能: ```go // Create 创建账号 // POST /api/admin/accounts func (h *AccountHandler) Create(c *fiber.Ctx) error { ``` **复杂方法**(超过 30 行或包含复杂业务逻辑)必须额外说明实现思路: ```go // ActivateByRealname 首次实名激活套餐 // 当用户完成实名认证后,自动激活处于"囤货待实名"状态的套餐: // 1. 查找该卡所有 status=3(待实名激活)的套餐 // 2. 按创建时间排序,第一个主套餐立即激活(status=1) // 3. 其余主套餐进入排队状态(status=4) // 4. 加油包如果绑定了已激活的主套餐则一并激活 func (s *UsageService) ActivateByRealname(ctx context.Context, cardID uint) error { ``` **未导出函数/方法**: - 简单逻辑(< 15 行):可以不加注释 - 复杂逻辑(≥ 15 行)或非显而易见的算法:必须加注释 ```go // buildPermissionTree 递归构建权限树 // 采用 map 索引 + 单次遍历算法,时间复杂度 O(n) func (s *Service) buildPermissionTree(permissions []*model.Permission) []*dto.PermissionTreeNode { ``` ## 常量和枚举注释 分组常量必须有组注释,每个值必须有行内注释: ```go // 用户类型常量 const ( UserTypeSuperAdmin = 1 // 超级管理员 UserTypePlatform = 2 // 平台用户 UserTypeAgent = 3 // 代理账号 UserTypeEnterprise = 4 // 企业账号 ) ``` ## 内联注释规范 **必须添加内联注释的场景**: | 场景 | 要求 | |------|------| | 复杂条件判断 | 解释判断的业务含义 | | 多步骤业务流程 | 用编号注释标明每一步 | | 非显而易见的设计决策 | 解释"为什么这样做"而不是"做了什么" | | 缓存/事务/并发处理 | 说明策略和原因 | | 临时方案/兼容逻辑 | 标注 TODO 或说明背景 | **✅ 好的内联注释(解释为什么)**: ```go // 使用 Redis 分布式锁防止并发重复创建,锁超时 10 秒 if !s.acquireLock(ctx, lockKey, 10*time.Second) { return errors.New(errors.CodeTooManyRequests, "操作过于频繁,请稍后重试") } // 先冻结佣金再扣款,保证资金安全(失败时佣金自动解冻) if err := s.freezeCommission(ctx, tx, orderID); err != nil { return err } ``` **❌ 废话注释(禁止)**: ```go // 获取用户ID ← 禁止:代码本身已经很清楚 userID := middleware.GetUserIDFromContext(ctx) // 创建账号 ← 禁止:变量名已说明意图 account := &model.Account{} // 返回错误 ← 禁止:return err 不需要注释 return err ```