Go 入门(12):时间处理——time 包用法
更新时间:2026-09-01。本文是
languages/go/beginner/入门层第 12 篇,接 正则表达式。Go 的time包提供了时间点、时长、定时器,格式化采用魔数2006-01-02 15:04:05,这是 Go 最具特色的设计之一。
本文要回答的问题
- Go 的时间格式化为什么用 2006-01-02?不是 %Y-%m-%d?
- time.Now() 返回的是本地时间还是 UTC?
- Duration 怎么用?怎么加减时间?
- 定时器 time.Sleep、time.After、time.Ticker 的区别?
一、时间格式化:2006-01-02 15:04:05
Go 不用 %Y-%m-%d,而是用一个具体的参考时间:
text
参考时间:Mon Jan 2 15:04:05 MST 2006
01 02 03 04 05 06 07格式化时,按这个参考时间写数字:
go
now := time.Now()
fmt.Println(now.Format("2006-01-02 15:04:05")) // 2026-09-01 14:30:00
fmt.Println(now.Format("2006/01/02")) // 2026/09/01
fmt.Println(now.Format("15:04:05")) // 14:30:00
fmt.Println(now.Format("2006-01-02T15:04:05Z07:00")) // ISO 8601 格式| 你要的格式 | 怎么写 |
|---|---|
| 年 | 2006 |
| 月 | 01 |
| 日 | 02 |
| 时(24 小时制) | 15 |
| 分 | 04 |
| 秒 | 05 |
| 周几 | Mon、Monday |
| 时区 | MST、-0700、Z07:00 |
为什么用这个数字? 因为 01 02 03 04 05 06 07 正好是月、日、时、分、秒、年、时区的数字,很好记——比 %Y-%m-%d 更直观。
二、解析时间字符串
go
// 解析 "2026-09-01 14:30:00" 为 time.Time
t, err := time.Parse("2006-01-02 15:04:05", "2026-09-01 14:30:00")
if err != nil {
log.Fatal(err)
}解析的格式字符串要和输入格式一致,否则解析失败。
三、Duration:时长
Duration 是纳秒数,用来计算时间差:
go
start := time.Now()
// 做点事情
time.Sleep(2 * time.Second)
elapsed := time.Since(start) // 等价于 time.Now().Sub(start)
fmt.Println(elapsed) // 2.000123456s
fmt.Println(elapsed.Milliseconds()) // 2000常用 Duration 常量:
go
time.Nanosecond // 1 ns
time.Microsecond // 1000 ns
time.Millisecond // 1000 μs
time.Second // 1000 ms
time.Minute // 60 s
time.Hour // 60 min时间加减:
go
now := time.Now()
tomorrow := now.Add(24 * time.Hour)
yesterday := now.Add(-24 * time.Hour)四、定时器
1. time.Sleep:阻塞等待
go
time.Sleep(3 * time.Second) // 等 3 秒2. time.After:返回一个 channel,到时发信号
go
select {
case <-time.After(3 * time.Second):
fmt.Println("timeout")
case result := <-ch:
fmt.Println("got result:", result)
}3. time.Ticker:周期性定时器
go
ticker := time.NewTicker(1 * time.Second)
for i := 0; i < 5; i++ {
<-ticker.C
fmt.Println("tick", i)
}
ticker.Stop() // 用完记得停止五、时区处理
go
// 加载时区
loc, _ := time.LoadLocation("Asia/Shanghai")
now := time.Now().In(loc)
fmt.Println(now.Format("2006-01-02 15:04:05 MST"))
// UTC 时间
utc := time.Now().UTC()
// 对比
local := time.Now()
fmt.Println(local.Format(time.RFC3339)) // 2026-09-01T14:30:00+08:00六、常见坑对照
| 坑 | 现象 | 对策 |
|---|---|---|
| 格式化字符串写错 | 输出乱码 | 永远用 2006-01-02 15:04:05 这个参考时间 |
| 忘记时区 | 系统时间和期望的不一致 | 明确用 UTC 或本地时间 |
| time.Sleep(1) | 睡 1 纳秒,不是 1 秒 | 写 time.Second,不要写数字 |
| Ticker 不 Stop | goroutine 泄漏 | 用 defer ticker.Stop() |
相关与延伸
下一篇:JSON 序列化——encoding/json 与 struct tag;time.After 和 goroutine 泄漏,进阶层讲;Go 的 time.Now 和系统调用,专家层和性能相关。
一句话总结
Go 时间处理:格式化用魔数 2006-01-02 15:04:05(月日时分秒年时区),比 %Y%m%d 好记;time.Now() 获取当前时间,time.Since() 计算过去时长;Duration 是纳秒,time.Second 等常量不要写裸数字;time.After 做超时,time.Ticker 做定时器,用完要 Stop。