Go语言时间控制核心是time包,需用time.Now().Format()按参考时间“2006-01-02 15:04:05”格式化,用time.Sleep(d)暂停协程并带单位,测试时应抽象nowFunc以便替换。

Go 语言里控制时间与日期,核心靠 time 包,最常用的是 time.Now() 获取当前时间、time.Sleep() 暂停执行。它们看着简单,但用对了才能写出稳定、可测试、不踩坑的代码。
用 time.Now() 获取并格式化当前时间
time.Now() 返回一个 time.Time 类型值,代表调用时刻的纳秒级精度时间(基于本地时区)。它不是字符串,不能直接打印成“2024-05-20 14:30:00”这种形式——得用 Format() 方法。
注意:Go 的时间格式化用的是“参考时间”(Mon Jan 2 15:04:05 MST 2006),不是常见的 YYYY-MM-DD。写错格式串会静默失败或输出空字符串。
- 标准 ISO8601 格式:
time.Now().Format("2006-01-02T15:04:05Z07:00") - 中文常用格式:
time.Now().Format("2006-01-02 15:04:05") - 带毫秒:
time.Now().Format("2006-01-02 15:04:05.000")
如果需要 UTC 时间,用 time.Now().UTC();要指定时区,可用 time.Now().In(loc),其中 loc, _ := time.LoadLocation("Asia/Shanghai")。
立即学习“go语言免费学习笔记(深入)”;
用 time.Sleep() 安全暂停程序
time.Sleep(d time.Duration) 让当前 goroutine 暂停指定时长,比如 time.Sleep(2 * time.Second)。它不会阻塞整个程序,只挂起当前协程。
- 别用整数秒直接传参:
time.Sleep(2)是错的,必须带单位,如time.Second、time.Millisecond - 避免硬编码大延迟:调试时写
time.Sleep(10 * time.Minute)很容易忘记删,上线后卡死服务 - 替代方案更可控:在循环或定时任务中,优先考虑
time.Ticker或time.AfterFunc(),比反复 Sleep 更清晰
让时间逻辑可测试:不要直接依赖 time.Now()
硬编码 time.Now() 会让单元测试无法控制时间,导致测试不稳定或无法覆盖边界场景(比如跨天、闰秒)。推荐把时间获取抽象成函数变量:
var nowFunc = time.Nowfunc getCurrentTime() time.Time { return nowFunc() }
// 测试时可替换 func TestSomething(t *testing.T) { saved := nowFunc defer func() { nowFunc = saved }() nowFunc = func() time.Time { return time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC) } // ... }
或者用接口方式(如 clock.Clock)进一步解耦,适合复杂项目。
常见误区与建议
- 别用
time.Now().Unix()做唯一 ID 或排序依据:同一纳秒内多次调用可能返回相同值;高并发下需配合原子计数器或使用time.Now().UnixNano() - 解析字符串时间要用
time.Parse(),注意时区:没指定时区的字符串默认按本地时区解析,容易出错;建议统一用 RFC3339 或带 Z 的格式 - 比较两个时间用
t1.Before(t2)、t1.Equal(t2),别用==——time.Time包含位置信息,直接比较可能不符合预期
基本上就这些。time 包设计简洁,但细节决定健壮性。用好 Now 和 Sleep,再加一点测试意识,时间逻辑就不会成为隐藏雷区。










