beego中time.time字段必须加type标签(如type(datetime)),否则建表失败或存为text;需配置parsetime=true、统一时区处理、filter传time.time值、json序列化手动格式化。

Beego模型中定义time.Time字段要加type标签
Beego的ORM(beeorm或旧版orm)不会自动识别time.Time为数据库时间类型,不加标签会导致建表时生成VARCHAR或报错。必须显式声明数据库列类型:
-
Created time.Time `orm:"auto_now_add;type(datetime)"`—— MySQL用datetime,PostgreSQL建议用timestamp with time zone -
Updated time.Time `orm:"auto_now;type(timestamp)"`—— 注意timestamp在MySQL里会受时区影响,datetime更稳定 - 若字段允许为空,补上
null:Expired *time.Time `orm:"null;type(datetime)"`
漏掉type标签是新手最常踩的坑:迁移后字段变成TEXT,查出来是空字符串或解析失败。
插入/更新时time.Time值被截断或时区错乱
Beego默认使用Go本地时区,但MySQL通常配置为SYSTEM或UTC,导致存入时间比预期快/慢8小时。关键不是改数据库,而是统一时区处理点:
- 在
main.go初始化前强制设置:time.Local = time.UTC(全局生效,慎用) - 更推荐在模型赋值时转UTC:
model.Created = time.Now().In(time.UTC) - 读取后如需本地显示,再转回:
t.In(time.Local)—— 不要在ORM层做自动转换 - 检查MySQL连接DSN是否含
parseTime=true,否则time.Time会被当作字符串返回
没开parseTime=true时,SELECT返回的Created字段是"0000-00-00 00:00:00"或直接panic,错误信息类似sql: Scan error on column index 2: unsupported driver -> Scan pair: []uint8 -> *time.Time。
查询时用QueryTable按日期范围过滤要避免字符串拼接
直接写"created__gte": "2024-01-01"看似可行,实则依赖数据库隐式转换,MySQL可能走不了索引,且跨时区结果不可靠:
- 正确做法是传
time.Time值:o.QueryTable(&User{}).Filter("created__gte", time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)) - 注意
Filter方法对时间字段只支持__gte、__lte等后缀,不支持__year这类语法 - 若需按“今天”查询,别用
time.Now(),而用time.Now().Truncate(24 * time.Hour)确保零点起始
字符串格式过滤(如"created__gte": "2024-01-01 00:00:00")在SQLite下可能正常,但在MySQL严格模式下直接报错Incorrect datetime value。
JSON序列化time.Time字段时格式不符合前端要求
Beego默认用Go内置json.Marshal,输出ISO8601带毫秒和时区(如"2024-03-15T08:30:00.123Z"),但前端常要"2024-03-15 08:30:00"这种格式:
- 不要重写整个结构体的
MarshalJSON,太重。改用Beego的Controller.Data["json"]预处理: data := map[string]interface{}{ "created": u.Created.Format("2006-01-02 15:04:05"), "name": u.Name, } c.Data["json"] = data c.ServeJSON()- 若大量模型复用,可封装一个
TimeJSON类型,实现MarshalJSON方法,但要注意它不能直接嵌套进原结构体字段(会破坏ORM映射)
试图通过json:"created,string"标签让Go输出字符串格式,会导致反序列化失败——Beego的ServeJSON不处理这个tag,只认标准json行为。











