Go 语言入门教程
time 包
本教程共 80 篇 · 第 74 篇 · 更新于 2026-07-27 · 约 8 分钟阅读
GoGo 入门教程timeDurationTickerTimer格式化时区
74. time 包
本节目标:掌握 time.Time 和 time.Duration,学会格式化时间的「模板」写法,用好 Ticker 和 Timer,理解时区处理。
获取当前时间
now := time.Now()
fmt.Println(now) // 2026-07-27 15:04:05.123456789 +0800 CST
time.Now() 返回当前本地时间。
创建指定时间
t1 := time.Date(2026, 7, 27, 15, 0, 0, 0, time.Local)
t2 := time.Date(2026, time.July, 27, 12, 0, 0, 0, time.UTC)
注意月份用 time.July 这种常量,不是数字 7,虽然效果一样但更清晰。
time.Duration
Duration 表示时间间隔,单位是纳秒:
var d time.Duration = 5 * time.Second
fmt.Println(d) // 5s
d2 := 500 * time.Millisecond
d3 := 2 * time.Hour
常用单位常量:
time.Nanosecond
time.Microsecond
time.Millisecond
time.Second
time.Minute
time.Hour
Tip别用
time.Sleep(5)这种写法,5 是纳秒等于没睡。一定要带单位:time.Sleep(5 * time.Second)。
时间运算
start := time.Now()
// 加减
later := start.Add(2 * time.Hour)
before := start.Add(-30 * time.Minute)
// 两个时间差
diff := later.Sub(start)
fmt.Println(diff) // 2h0m0s
// 比较
start.Before(later) // true
start.After(later) // false
start.Equal(start) // true
格式化时间(重点)
Go 的时间格式化很特别,不用 YYYY-MM-DD,而是用一个参考时间当模板:
2006-01-02 15:04:05
这个时间是 1月2日下午3点4分5秒 2006年,对应 1 2 3 4 5 6。记住「1-2-3-4-5-6」就行。
now := time.Now()
// 格式化
s := now.Format("2006-01-02 15:04:05")
fmt.Println(s) // 2026-07-27 15:04:05
s2 := now.Format("2006/01/02")
fmt.Println(s2) // 2026/07/27
s3 := now.Format("15:04")
fmt.Println(s3) // 15:04
Warning格式化字符串里写错数字就出不来正确结果。
2006是年、01是月、02是日、15是时(24小时制)、04是分、05是秒。写2024-01-02这种常见错误是无效的。
常用模板速查:
| 模板 | 效果 |
|---|---|
2006-01-02 | 2026-07-27 |
15:04:05 | 15:04:05 |
2006-01-02 15:04:05 | 2026-07-27 15:04:05 |
20060102 | 20260727 |
2006-01-02T15:04:05Z07:00 | RFC3339 格式 |
Jan 2, 2006 | Jul 27, 2026 |
2006-01-02 03:04:05 PM | 2026-07-27 03:04:05 PM(12小时制) |
解析时间字符串
time.Parse 把字符串解析成 Time:
t, err := time.Parse("2006-01-02", "2026-07-27")
if err != nil {
fmt.Println("解析失败:", err)
}
fmt.Println(t) // 2026-07-27 00:00:00 +0000 UTC
Parse 按时区 UTC 解析。想按本地时区用 ParseInLocation:
loc, _ := time.LoadLocation("Asia/Shanghai")
t, _ := time.ParseInLocation("2006-01-02 15:04:05", "2026-07-27 15:00:00", loc)
时间戳
now := time.Now()
sec := now.Unix() // 秒级时间戳
nano := now.UnixNano() // 纳秒级时间戳
milli := now.UnixMilli() // 毫秒级时间戳(Go 1.17+)
// 从时间戳还原
t := time.Unix(sec, 0)
Timer 定时器
Timer 到时间触发一次:
timer := time.NewTimer(2 * time.Second)
fmt.Println("等待中...")
<-timer.C // 阻塞 2 秒
fmt.Println("时间到")
// 提前停止
timer.Stop()
time.After 是简化版,直接返回一个只读 channel:
<-time.After(2 * time.Second) // 等 2 秒
Ticker 周期触发
Ticker 按固定间隔重复触发:
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for i := 0; i < 5; i++ {
<-ticker.C
fmt.Println("tick", i)
}
配合 select 可以实现定时任务和超时:
ticker := time.NewTicker(500 * time.Millisecond)
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
for {
select {
case <-ticker.C:
fmt.Println("干活")
case <-ctx.Done():
fmt.Println("结束")
return
}
}
时区处理
// 获取时区
loc, err := time.LoadLocation("Asia/Shanghai")
loc2, err := time.LoadLocation("America/New_York")
// 在指定时区显示时间
now := time.Now()
shanghaiTime := now.In(loc)
nyTime := now.In(loc2)
fmt.Println(shanghaiTime.Format("2006-01-02 15:04:05"))
fmt.Println(nyTime.Format("2006-01-02 15:04:05"))
Note服务端处理时间建议内部统一用 UTC,只在展示时转成用户时区。数据库存 UTC,前端按需转换。这样能避免很多时区混乱问题。
小结
time.Now()取当前时间,time.Date()创建指定时间Duration表示间隔,必须带单位(5 * time.Second)- 格式化用参考时间
2006-01-02 15:04:05当模板 time.Parse解析字符串,注意时区Timer触发一次,Ticker周期触发- 内部用 UTC,展示时转时区
下一节讲 encoding/json。