import (
"time"
"math/rand"
)
// invalid operation: rand.Intn(10) * 1000 * time.Millisecond (mismatched types int and time.Duration)
time.Sleep(rand.Intn(10) * 1000 * time.Millisecond) ❌
// 🤔 make sense.
time.Sleep(time.Duration(rand.Intn(10) * 1000) * time.Millisecond) ✅
// wtf ?!
time.Sleep(1000 * time.Millisecond) ✅ 看看上面这个简单的例子:
time.Duration 相乘1000 * time.Millisecond 却没有问题?明明 1000 也是个整型?编译器戴了有色眼镜?别慌,仔细看看 rand.Intn(10) * 1000 和 1000 的区别在于:前者是变量,类型已经确定了,通不过编译是情理之中;而后者是常量,类型并不是 int ,属于 untyped constants ,编译器会尝试将它转换成 time.Duration 。
这就勾起了我的好奇心,那如果我写个一个 float 常量会怎样呢?
// (untyped float constant) truncated to int64
time.Sleep(1000.1 * time.Millisecond) ❌果然是不行的。那么究竟这个无类型常量的类型转换是依照什么规则进行的呢?
首先每一种常量的写法都会对应着一种默认类型:

然后,看看 time.Duration 的定义:
type Duration int64
const (
Nanosecond Duration = 1
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute
)也就是说 1000 的写法默认类型为 int ,编译器会尝试做一次类型转换 int → time.Duration ,而 int64 和 int 又能做到完全兼容,所以编译通过。
WTF,Go…