问题

最近需要使用 rand 包随机 time.Sleep() 的时间, 我的代码是这样的:

package main

import (
	"math/rand"
	"time"
)

func main() {
	rand.Seed(time.Now().UTC().UnixNano())
	n := rand.Intn(10)
	time.Sleep(n * time.Second)
}

会遇到下面的问题:

Cannot use 'n * time.Second' (type int) as the type Duration
Invalid operation: n * time.Second (mismatched types int and Duration)

解决的方法

使用 time.Duration 转换类型,代码如下:

package main

import (
	"math/rand"
	"time"
)

func main() {
	rand.Seed(time.Now().UTC().UnixNano())
	n := rand.Intn(10)
	time.Sleep(time.Duration(n) * time.Second)
}

问题的原因

time.Sleep 方法接收的类型是 Duration 类型。

func Sleep(d Duration)

当我们要 sleep 5s时, 参数是 5 * time.Second, Second 又是 1000 * Millisecond, Millisecond 是 1000 * Microsecond,Microsecond 是 1000 * Nanosecond,Nanosecond 是 1纳秒,它的类型就是 Duration。最后 5s 就变成 5000000000数值。

问题的引申

在我们使用 sleep方法时, 可以发现我们可以直接使用 time.Sleep(2 * time.Second), 这是为什么呢?

package main

import (
	"time"
)

func main() {
	time.Sleep(time.Duration(2) * time.Second)
	time.Sleep(2 * time.Second)
}

通过 go tool compile -S main.go 生成汇编代码,通过分析可以看出 golang 已经帮我们优化了 time.Duration 的转换。

img.png