Go中的time是一个日常开发中经常用到的package。这里总结一些常用的方式。
获取当前的时间
1
2
3
4
5
6
7
|
import (
"time"
"fmt"
)
now := time.Now()
fmt.Println("current time:", now)
|
time.Now()
返回的是一个Time
对象。上面的代码示例的输出结果为:
current time: 2024-11-06 18:10:25.099407 +0800 CST m=+0.000157959
其中 +0800表示当前的时间是UTC+8的时间,CST是China Standard Time
,中国标准时间。
这样的时间格式不一定是我们需要的,所以我们可以用Time对象的Format方法对它进行格式化处理,
1
|
fmt.Println(now.Format("2006-01-02 15:04:05"))
|
睡眠 time.Sleep
time.Sleep() 用于让当前的goroutine暂停执行,让协程调度器执行其它的goroutine。
1
2
|
// 睡眠10秒
time.Sleep(10 * time.Second)
|
定时器 time.NewTimer()
Timer是time包中有一个很重要的type,它会以当前时间为起点,在值得的时间周期到后,触发Timer,然后Timer会给自己的一个Channel中发送一个时间值。
time.NewTimer()就是返回一个Timer对象,我们可以读取这个对象的C通道,实现time.Sleep类似的效果。
1
2
3
4
|
timer := time.NewTimer(10 * time.Second)
defer timer.Stop()
<- timer.C // 在十秒达到前,这里会被阻塞,实现了sleep的效果。
|
Timer有两个主要的应用场景:
超时检测
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
func makeNetworkRequest() (string, error) {
// 模拟网络请求,这里假设需要 10 秒才能完成
time.Sleep(10 * time.Second)
return "Response from network", nil
}
func main() {
// 创建一个 5 秒超时的 Timer
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
// 并发执行网络请求和超时检测
done := make(chan string)
go func() {
resp, err := makeNetworkRequest()
if err != nil {
done <- err.Error()
} else {
done <- resp
}
}()
select {
case res := <-done:
fmt.Println("Request completed:", res)
case <-timer.C:
fmt.Println("Request timed out")
}
}
|
超时控制,除了使用time.NewTimer()的方式,还可以使用time.After(),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
func (s *Server) performScan(path string) (string, error) {
c := clamd.NewClamd(s.ClamAVDaemonHost)
responseCh := make(chan chan *clamd.ScanResult)
errCh := make(chan error)
go func(responseCh chan chan *clamd.ScanResult, errCh chan error) {
response, err := c.ScanFile(path)
if err != nil {
errCh <- err
return
}
responseCh <- response
}(responseCh, errCh)
select {
case err := <-errCh:
return "", err
case response := <-responseCh:
st := <-response
return st.Status, nil
case <-time.After(time.Second * 60):
return "", errors.New("clamav scan timeout")
}
}
|
上面的代码片段是从 https://sourcegraph.com/github.com/dutchcoders/transfer.sh/-/blob/server/clamav.go?L98-100 获取到的,可以看到,当扫描一个路径超过60秒后,就会超时返回错误。
延迟执行
延迟执行是指让干某件事先延迟一段时间,再执行,例如下面的代码:
1
2
3
4
5
6
7
8
9
10
11
12
|
func doSomethingLater() {
fmt.Println("Doing something later")
}
func main() {
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
<-timer.C // // 延迟 5 秒后执行 doSomethingLater 函数
doSomethingLater()
}
|
在上面的延迟场景中,用time.Sleep(5 * time.Second)
也可以实现延迟效果。
周期执行 time.NewTicker()
time.NewTicker()可以周期性地重复执行某个任务。
比如,我想让程序每秒打印一次统计数据,则可以使用Ticker
1
2
3
4
5
6
|
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for range ticker.C {
// do something
}
|