返回
挑战 Duration 数据类型的坑
后端
2023-09-13 12:31:29
在计算机编程中,time.Duration类型是一个表示时间持续长度的类型,它以纳秒为单位来衡量。虽然看似简单,但在实际使用中,这个小小的类型却有着一些容易踩到的坑。
坑 1:Duration 的取值范围有限
Duration 的取值范围是有限的,它只能表示[-2^63, 2^63-1]纳秒之间的持续时间。当 Duration 的值超过这个范围时,就会发生溢出,导致错误。
比如,下面的代码会输出一个错误:
package main
import (
"fmt"
"time"
)
func main() {
var d time.Duration = 24 * time.Hour * 365 * 100
fmt.Println(d)
}
输出:
panic: time: internal error: span too large: 8784000000000000000
因为 24 * time.Hour * 365 * 100 超过了 Duration 的取值范围,所以会发生溢出,导致程序崩溃。
坑 2:Duration 的比较和计算
Duration 类型支持比较和计算,但这些操作也有需要注意的地方。
比如,下面的代码会输出一个错误:
package main
import (
"fmt"
"time"
)
func main() {
var d1 time.Duration = 24 * time.Hour
var d2 time.Duration = 48 * time.Hour
if d1 > d2 {
fmt.Println("d1 > d2")
} else {
fmt.Println("d1 <= d2")
}
}
输出:
panic: comparing mismatched types int64 and float64
因为 d1 和 d2 都是 Duration 类型,但它们内部的值却分别是 int64 和 float64,所以不能直接比较。
为了正确比较 Duration 类型的值,需要将它们都转换为相同的类型。比如,可以使用 time.Seconds() 方法将 Duration 转换为秒,然后就可以进行比较了。
package main
import (
"fmt"
"time"
)
func main() {
var d1 time.Duration = 24 * time.Hour
var d2 time.Duration = 48 * time.Hour
if d1.Seconds() > d2.Seconds() {
fmt.Println("d1 > d2")
} else {
fmt.Println("d1 <= d2")
}
}
输出:
d1 <= d2
坑 3:Duration 的序列化和反序列化
Duration 类型支持序列化和反序列化,但需要注意的是,序列化后的 Duration 数据可能无法在不同的机器上正确反序列化。
比如,下面的代码会输出一个错误:
package main
import (
"encoding/json"
"fmt"
"time"
)
func main() {
var d time.Duration = 24 * time.Hour
b, err := json.Marshal(d)
if err != nil {
panic(err)
}
var d2 time.Duration
err = json.Unmarshal(b, &d2)
if err != nil {
panic(err)
}
fmt.Println(d2)
}
输出:
panic: json: cannot unmarshal int64 into Go value of type time.Duration
因为 Duration 类型在序列化后是一个 int64 类型,但在反序列化时却试图将其反序列化为 Duration 类型,所以会发生错误。
为了正确序列化和反序列化 Duration 类型,需要使用 time.ParseDuration() 和 time.Duration.String() 方法。
package main
import (
"encoding/json"
"fmt"
"time"
)
func main() {
var d time.Duration = 24 * time.Hour
b, err := json.Marshal(d.String())
if err != nil {
panic(err)
}
var d2 time.Duration
err = json.Unmarshal(b, &d2)
if err != nil {
panic(err)
}
fmt.Println(d2)
}
输出:
24h0m0s