[英]How to multiply duration by integer?
为了测试并发 goroutine,我在 function 中添加了一行,让它随机返回(最多一秒)
time.Sleep(rand.Int31n(1000) * time.Millisecond)
但是当我编译时,我得到了这个错误
.\crawler.go:49:无效操作:rand.Int31n(1000) * time.Millisecond(不匹配类型 int32 和 time.Duration)
有任何想法吗? 我怎样才能乘以持续时间?
int32
和time.Duration
是不同的类型。 您需要将int32
转换为time.Duration
:
time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond)
您必须将其转换为正确的格式Playground 。
yourTime := rand.Int31n(1000)
time.Sleep(time.Duration(yourTime) * time.Millisecond)
如果您检查sleep 的文档,您会看到它需要func Sleep(d Duration)
duration 作为参数。 您的rand.Int31n返回int32
。
示例中的行( time.Sleep(100 * time.Millisecond)
)有效,因为编译器足够聪明,可以理解这里的常量100 表示持续时间。 但是如果你传递一个变量,你应该强制转换它。
在 Go 中,您可以将相同类型的变量相乘,因此您需要让表达式的两个部分具有相同的类型。
您可以做的最简单的事情是在乘法之前将整数转换为持续时间,但这会违反单位语义。 就单位而言,持续时间乘以持续时间是多少?
我宁愿将 time.Millisecond 转换为 int64,然后将其乘以毫秒数,然后转换为 time.Duration:
time.Duration(int64(time.Millisecond) * int64(rand.Int31n(1000)))
这样,表达式的任何部分都可以说根据其类型具有有意义的值。 int64(time.Millisecond)
部分只是一个无量纲值 - 原始值中最小时间单位的数量。
如果走一条稍微简单的路径:
time.Duration(rand.Int31n(1000)) * time.Millisecond
乘法的左边部分是无稽之谈——一个“time.Duration”类型的值,持有与其类型无关的东西:
numberOfMilliseconds := 100
// just can't come up with a name for following:
someLHS := time.Duration(numberOfMilliseconds)
fmt.Println(someLHS)
fmt.Println(someLHS*time.Millisecond)
这不仅仅是语义,还有与类型相关的实际功能。 此代码打印:
100ns
100ms
有趣的是,这里的代码示例使用了最简单的代码,同样具有 Duration 转换的误导语义: https : //golang.org/pkg/time/#Duration
秒:= 10
fmt.Print(time.Duration(seconds)*time.Second) // 打印 10s
Go 有一个Duration
类型很好——明确定义的单位可以防止现实世界的问题。
而且由于 Go 的严格类型规则,您不能将 Duration 乘以整数——您必须使用强制转换才能乘以常见类型。
/*
MultiplyDuration Hide semantically invalid duration math behind a function
*/
func MultiplyDuration(factor int64, d time.Duration) time.Duration {
return time.Duration(factor) * d // method 1 -- multiply in 'Duration'
// return time.Duration(factor * int64(d)) // method 2 -- multiply in 'int64'
}
官方文档演示了使用方法#1:
要将整数单位转换为持续时间,请乘以:
seconds := 10
fmt.Print(time.Duration(seconds)*time.Second) // prints 10s
但是,当然,将持续时间乘以持续时间不应产生持续时间——从表面上看,这是荒谬的。 例如,5 毫秒乘以 5 毫秒产生6h56m40s
。 尝试平方 5 秒会导致溢出(如果使用常量完成,甚至不会编译)。
顺便说一句,以纳秒为单位的Duration
的int64
表示“将最大可表示的持续时间限制为大约 290 年” ,这表明Duration
与int64
一样,被视为有符号值: (1<<(64-1))/(1e9*60*60*24*365.25) ~= 292
,这就是它的实现方式:
// A Duration represents the elapsed time between two instants
// as an int64 nanosecond count. The representation limits the
// largest representable duration to approximately 290 years.
type Duration int64
所以,因为我们知道Duration
的底层表示是一个int64
,在int64
和Duration
之间执行转换是一个明智的 NO-OP —— 只需要满足关于混合类型的语言规则,它对后续的乘法运算没有影响.
如果您出于纯度的原因不喜欢铸造,请将其埋在函数调用中,如我上面所示。
对一些关于将Duration
与Duration
相乘的评论和讨论感到困惑,我对单位和函数进行了一些尝试并得到了这个:
time.Second = 1s
time.Minute = 1m0s
time.Duration(1) = 1ns
time.Duration(1) * time.Millisecond = 1ms
time.Duration(1) * time.Second = 1s
time.Duration(1) * time.Minute = 1m0s
像这样乘以它:
time.Sleep(1000 * time.Millisecond)
你不需要转换它。
推理:
1000
是一个无类型文字常量,默认类型为 integer,它有一个理想类型。
1000 * time.Millisecond
可以直接使用,因为 Go 会自动将无类型常量转换为数字类型。 在这里,它自动将1000
转换为time.Duration
,因为它是Int64的别名。
毫秒定义如下:
type Duration int64
const (
Nanosecond Duration = 1
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute
)
Millisecond
具有time.Duration
类型,但在底层,它是一个int64
类型,它是可赋值的,可以被无类型的数字 integer使用。
我在这篇文章中写了这些细节。
轮到我了:
https://play.golang.org/p/RifHKsX7Puh
package main
import (
"fmt"
"time"
)
func main() {
var n int = 77
v := time.Duration( 1.15 * float64(n) ) * time.Second
fmt.Printf("%v %T", v, v)
}
它有助于记住一个简单的事实,即 time.Duration 的底层只是一个 int64,它包含纳秒值。
这样,转换到/从 time.Duration 变成了一种形式。 请记住:
您也可以使用time.ParseDuration 。
s := 4
duration, err := time.ParseDuration(fmt.Sprintf(
"%vs",
s,
))
ms := 4000
duration, err := time.ParseDuration(fmt.Sprintf(
"%vms",
ms,
))
用于将变量乘以 time.Second 使用以下代码
oneHr:=3600
addOneHrDuration :=time.Duration(oneHr)
addOneHrCurrTime := time.Now().Add(addOneHrDuration*time.Second)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.