1. 问题现象与背景
最近在开发一个Go语言后端服务时,遇到了一个让人头疼的问题:从MySQL数据库查询出来的时间字段,在代码中显示总是比实际存储的时间少8小时。这个问题看似简单,却让我花了整整一个下午的时间排查。相信不少使用Go语言操作MySQL的开发者都遇到过类似的时区问题。
具体表现为:
- 数据库中存储的时间是
2023-08-15 14:30:00 - 通过Go程序查询后,得到的时间却是
2023-08-15 06:30:00 - 时间值少了8小时,正好是UTC与北京时间(CST)的时区差
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 时区问题的根源分析
2.1 MySQL时区配置
MySQL服务器默认使用系统时区,可以通过以下命令查看当前时区设置:
sql复制SHOW VARIABLES LIKE '%time_zone%';
如果输出显示SYSTEM,表示MySQL使用操作系统时区。在中国大陆的服务器上,通常会是CST(China Standard Time,UTC+8)。
2.2 Go语言时区处理
Go语言的time.Time类型在解析数据库时间时,默认会将其视为UTC时间。这就是为什么从MySQL查询出的时间会少8小时的原因。
Go的database/sql驱动在扫描时间类型时,会调用time.Parse()函数,而该函数默认将时间字符串解析为UTC时间。
2.3 连接参数的影响
在使用Go连接MySQL时,连接字符串中的parseTime和loc参数会影响时间解析行为:
go复制dsn := "user:password@tcp(127.0.0.1:3306)/dbname?parseTime=true&loc=Local"
parseTime=true:告诉驱动将DATE和DATETIME值解析为Go的time.Time类型loc=Local:指定时区位置,但这里的"Local"指的是Go程序运行环境的时区
3. 解决方案与实践
3.1 方案一:统一使用UTC时间(推荐)
go复制// 连接字符串中明确指定UTC时区
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?parseT
