★ GoFrame 常见坑(ctx 首参、指针接收、时区等)

面试问法:用 GoFrame 开发时你踩过哪些坑?怎么避免? 一句话结论:高频坑集中在五类——ctx 没有作为首参贯穿、do/entity/dao 模型混用、时区与 gtime/time.Time 混用、事务内没用对连接、以及路由/校验对结构体的隐式约定。多数坑都能靠“遵守官方分层与签名约定”规避。

高频坑清单

  1. ctx 不贯穿:dao、日志、链路追踪都需要带 ctx;漏传会导致事务/追踪信息丢失。约定:controller → service → dao 每个方法首参都是 ctx。
  2. 模型混用:读数据用 entity、写与条件构造用 do(指针表达“未设置”),把 do 当 entity 扫描或反之都容易出错。
  3. 时区:连接串不带 loc=Local&parseTime=true、或 time.Parse 得到 UTC 时间,条件查询偏差 8 小时(见 gtime 章节)。
  4. gtime 与 time.Time 混用:JSON 序列化格式不同(gtime 输出 2006-01-02 15:04:05),接口层与持久层类型要保持一致。
  5. 事务内仍用不带事务的 dao:事务要在 g.DB().Transaction 回调内用回调 ctx / tx 操作,事务外查询不会自动加入事务。
  6. 结构体约定破坏:规范路由 handler 必须 (ctx, req) (res, err) 签名、Req/Res 命名带后缀,否则路由注册或参数绑定异常。
  7. 校验与 JSON 标签顺序:v 规则与字段顺序、bail 修饰影响失败即停;含 required 规则建议放最前。
  8. 分层循环依赖:controller 依赖 service、service 依赖 dao 是单向的;api 结构体独立成包,避免 api ↔ internal 互相 import。
  9. 生产开着 debug:SQL 全量打印 + 堆栈,性能断崖;部署前检查 database.default.debug: false
  10. Model 对象复用:带链式状态的 Model 跨请求/跨 goroutine 复用有竞态,每个请求从 dao.Xxx.Ctx(ctx) 现取。

两个典型代码对比

// 坑:事务外自建连接、丢了 ctx
g.DB().Model("user").Data(g.Map{"name": "a"}).Insert() // 不在事务内

// 正:事务回调内操作(tx 或回调 ctx 传入的 dao 用法以官方文档为准)
err := g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
    // 使用事务对象或按官方文档经 ctx 绑定事务的 dao 写法
    return nil
})
// 坑:time.Parse 得到 UTC,入库/比较偏 8 小时
t, _ := time.Parse("2006-01-02 15:04:05", "2024-01-02 10:00:00")
// 正:用本地时区解析
t, _ := time.ParseInLocation("2006-01-02 15:04:05", "2024-01-02 10:00:00", time.Local)

常见追问

  • 追问:异步 goroutine 里能用请求的 r 对象吗?——不能;请求结束对象会被框架回收复用,只把 ctx(或必要值)传出去。
  • 追问:SetTimeZone 为什么有时不生效?——标准库 time 在 import 初始化时会固定时区;要把设置放独立包并在 main 最前面空导入,否则只能对对象逐个 ToLocation。

记忆点

  • 三守则:ctx 首参贯穿、类型用对(entity/do/gtime)、约定别破坏(分层、签名、时区)。
笔记加载中…