6.6 测试、调试与日志

测试、调试与日志

运行测试

# 全部测试
go test ./...

# 带覆盖率
go test -cover ./...

# 竞态检测(开发必跑一次)
go test -race ./...

# 单个测试文件
go test ./pkg/helper/signature_helper_test.go

# 指定测试函数
go test ./pkg/helper/ -run TestSignature

编写单元测试

建议测试放在被测文件同目录下,命名 xxx_test.go

package helper

import "testing"

func TestBase62Encode(t *testing.T) {
    cases := []struct {
        in  uint64
        out string
    }{
        {1, "1"},
        {62, "10"},
    }
    for _, c := range cases {
        if got := Encode(c.in); got != c.out {
            t.Errorf("Encode(%d) = %q, want %q", c.in, got, c.out)
        }
    }
}

推荐依赖:标准库 testing 足够;复杂场景可用 github.com/stretchr/testify/assert

避免真 DB 依赖

单元测试尽量不要依赖真实数据库。做法:

  • 对 DAO 层,可用 SQLite 内存模式(file::memory:?cache=shared)做集成测试
  • 对 Service 层,通过接口抽象 DAO,用 mock 替换
  • 完整端到端测试放到 test/integration/ 目录单独执行

调试技巧

使用 Delve

go install github.com/go-delve/delve/cmd/dlv@latest
dlv debug main.go
(dlv) break app/controller/short_link_controller.go:42
(dlv) continue

GoLand / VS Code 调试

  • GoLand:右键 main.go → Debug
  • VS Code:创建 .vscode/launch.json,Mode = debug,Program = ${workspaceFolder}

启动时打开 debug 模式

http:
  mode: debug

Gin 会打印完整的路由表和请求详情,方便定位路由问题。

日志

项目使用 Zap。获取 logger:

logger := helper.GetLogger()
logger.Info("处理短链接", zap.String("code", code), zap.Uint64("id", id))
logger.Error("创建失败", zap.Error(err))

日志级别约定

级别 用途
Debug 开发期详细信息,生产默认不输出
Info 关键业务事件(登录、创建、删除)
Warn 异常但可恢复(重试成功、降级路径)
Error 错误且影响本次请求
Fatal 程序无法继续,谨慎使用

日志配置

log:
  level: info          # debug / info / warn / error
  filename: logs/app.log
  max_size: 100        # MB
  max_age: 30          # days
  max_backups: 10
  compress: true

常见调试场景

现象 排查方向
路由 404 检查 router.go 是否注册、前缀是否一致
401 未认证 确认请求头 Authorization: Bearer <token>、Token 未过期
跳转 500 查看日志 short_link_service 相关 error
数据库连接失败 检查 config.yaml DSN、DB 服务可达性、用户权限
缓存未命中 切到 cache.driver: local 排除 Redis 故障