time.Now() 返回本地时区时间,非UTC或固定时区;格式化须用“2006-01-02 15:04:05”模板;解析需检查err;高并发下调用性能无虞,但避免频繁Format。

time.Now() 返回的是本地时区时间,不是 UTC,也不是固定时区 —— 这是绝大多数人第一次用就踩坑的地方。
为什么 time.Now() 输出的时间和你预期的时区对不上
Go 的 time.Now() 默认使用系统本地时区(由 TZ 环境变量或操作系统配置决定),不是 UTC,也不是北京时间(Asia/Shanghai)。如果你在服务器上跑,而服务器时区是 UTC,那 time.Now().Format("2006-01-02 15:04:05") 就会输出 UTC 时间,看着像“慢了 8 小时”。
- 检查当前时区:
time.Now().Location().String() - 硬指定北京时区:用
time.LoadLocation("Asia/Shanghai"),再调time.Now().In(loc) - UTC 场景更推荐统一用
time.Now().UTC(),比依赖本地时区更可控 - Docker 容器里默认是 UTC,不显式设置时区的话,
time.Now()就是 UTC
格式化时间时 panic:“cannot parse time” 或输出空字符串
Go 的时间格式化不是用 %Y-%m-%d 那套,而是用一个具体时间值 "2006-01-02 15:04:05" 作模板(称为“magic number”),写错一位、多一个空格、大小写不对(如 MM vs mm)都会导致 time.Parse 失败,但 Format 不会 panic —— 它只是静默输出空字符串或乱码。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
-
"2006-01-02 15:04:05"是唯一正确的参考模板(年份必须是 2006,月份是 01,小时是 15) - 年份用
2006,不是yyyy;星期用Monday或Mon,不是dddd - 解析字符串时,务必检查
err:t, err := time.Parse("2006-01-02", "2024-05-10") - 想兼容多种输入格式?别硬刚
Parse,用ParseInLocation+ 显式传入时区,避免隐式本地时区干扰
高并发下频繁调用 time.Now() 会影响性能吗
不会。Go 运行时对 time.Now() 做了优化,底层调用的是 vDSO(Linux)或类似高效系统调用,单次耗时在纳秒级,远低于一次函数调用开销。日常业务中完全不用缓存或节流。
立即学习“go语言免费学习笔记(深入)”;
- 微基准测试显示:百万次调用
time.Now()耗时约 20–30ms(现代 CPU) - 真正要小心的是把
time.Now()放在 hot path 里做字符串格式化(Format是相对重的操作) - 如果只是记录毫秒时间戳用于计算间隔,直接用
time.Since(start)或t.UnixMilli(),比格式化快一个数量级 - 日志打点等场景,建议用结构化日志库(如
zerolog)内置的时间字段,避免重复调用和格式化
真正麻烦的从来不是怎么取时间,而是时区在哪、格式模板记没记混、解析失败有没有判 err —— 这三处漏掉任何一个,线上就容易出“时间对不上”的玄学问题。

















