Go语言定时器的用法(附带实例)
定时器使我们能够延迟执行任务或定期执行任务。Go 语言的 time 包提供了与时间和定时器相关的 API,例如获取当前系统时间(精确到纳秒级)、让协程休眠指定时间、延迟指定时间执行任务等。
下面我们通过几个 Go 程序进行演示:
1) 第一个程序演示了如何让协程休眠指定时间,代码如下所示:
注意,实际上主协程至少会暂停 3s,也有可能暂停更长时间,因为如果 Go 程序任务比较繁忙,那么 3s 之后即使主协程可以运行,也可能无法被调度器调度执行。
方法 Format 用于格式化输出时间,注意上面使用的格式是 2006-01-02 15:04:05,这有什么特殊含义吗?使用其他格式如 2023-03-25 20:27:21可以吗?按理说这两个时间字符串的格式一样,只是值不一样罢了,结果应该没区别。我们可以编写一个简单的 Go 程序进行测试,代码如下所示:
这就需要研究下 Go 语言的 Format 方法支持的格式标识,比如其他一些语言使用 Y 表示年,M 表示月等。Go 语言定义的年月日等标识如下所示:
2) 第二个程序演示如何延迟指定时间执行某项任务,代码如下所示:
可以看到,结果符合我们的预期。
3) 第三个程序演示如何周期性执行某项任务,代码如下所示:
下面我们通过几个 Go 程序进行演示:
1) 第一个程序演示了如何让协程休眠指定时间,代码如下所示:
package main import ( "fmt" "time" ) func main() { fmt.Println("main start:", time.Now().Format("2006-01-02 15:04:05")) // 协程休眠 3s time.Sleep(3 * time.Second) fmt.Println("main end:", time.Now().Format("2006-01-02 15:04:05")) }输出结果为:
main start: 2025-08-21 09:51:50
main end: 2025-08-21 09:51:53
注意,实际上主协程至少会暂停 3s,也有可能暂停更长时间,因为如果 Go 程序任务比较繁忙,那么 3s 之后即使主协程可以运行,也可能无法被调度器调度执行。
方法 Format 用于格式化输出时间,注意上面使用的格式是 2006-01-02 15:04:05,这有什么特殊含义吗?使用其他格式如 2023-03-25 20:27:21可以吗?按理说这两个时间字符串的格式一样,只是值不一样罢了,结果应该没区别。我们可以编写一个简单的 Go 程序进行测试,代码如下所示:
package main import ( "fmt" "time" ) func main() { fmt.Println(time.Now().Format("2023-03-25 20:27:21")) }输出结果为:
21219-09-214 210:217:218
参考上面的程序,输出结果是一个很奇怪的字符串,并不是我们想要的年月日时分秒格式。这是为什么呢?这就需要研究下 Go 语言的 Format 方法支持的格式标识,比如其他一些语言使用 Y 表示年,M 表示月等。Go 语言定义的年月日等标识如下所示:
const ( stdZeroMonth = iota + stdNeedDate // "01" stdZeroDay // "02" stdHour // "15" stdZeroMinute // "04" stdZeroSecond // "05" stdLongYear // "2006" // 省略了其他标识定义 )看到了吧,2006、01 等才是 Go 语言定义的时间格式标识,所以 2006-01-02 15:04:05才能正常显示年月日时分秒。当然,这里还省略了很多其他时间格式标识,可以参考 time/format.go 文件。
2) 第二个程序演示如何延迟指定时间执行某项任务,代码如下所示:
package main import ( "fmt" "time" ) func main() { fmt.Println("main start:", time.Now().Format("2006-01-02 15:04:05")) // 1 s 后执行函数 time.AfterFunc(time.Second, func() { fmt.Println("exec task:", time.Now().Format("2006-01-02 15:04:05")) }) time.Sleep(3 * time.Second) }输出结果为:
main start: 2025-08-21 09:54:26
exec task: 2025-08-21 09:54:27
- 第一个参数表示延迟时间;
- 第二个参数是函数类型,表示需要延迟执行的函数。
可以看到,结果符合我们的预期。
3) 第三个程序演示如何周期性执行某项任务,代码如下所示:
package main import ( "fmt" "time" ) func main() { fmt.Println("main start:", time.Now().Format("2006-01-02 15:04:05")) // 以 1 s 为周期,定时触发 ticker := time.NewTicker(time.Second) go func() { for { <-ticker.C // 时间触发时,管道可读 fmt.Println("exec task:", time.Now().Format("2006-01-02 15:04:05")) } }() time.Sleep(3 * time.Second) }输出结果为:
main start: 2025-08-21 09:55:30
exec task: 2025-08-21 09:55:31
exec task: 2025-08-21 09:55:32