如何将持续时间乘以整数?

时间:2013-07-10 14:23:45

标签: go

为了测试并发goroutine,我在函数中添加了一行,使其需要随机时间返回(最多一秒)

time.Sleep(rand.Int31n(1000) * time.Millisecond)

但是当我编译时,我收到了这个错误

  

。\ crawler.go:49:无效操作:rand.Int31n(1000)* time.Millisecond(不匹配类型int32和time.Duration)

有什么想法吗?如何乘以持续时间?

6 个答案:

答案 0 :(得分:291)

int32time.Duration是不同的类型。您需要将int32转换为time.Duration,例如time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond)

答案 1 :(得分:38)

您必须将其转换为正确的格式 Playground

yourTime := rand.Int31n(1000)
time.Sleep(time.Duration(yourTime) * time.Millisecond)

如果您要检查sleep的文档,则会看到它需要func Sleep(d Duration)个持续时间作为参数。您的rand.Int31n会返回int32

示例中的行有效(time.Sleep(100 * time.Millisecond)),因为编译器足够聪明,可以理解,constant 100表示​​持续时间。但是如果你传递一个变量,你应该投射它。

答案 2 :(得分:9)

在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

有趣的是,此处的代码示例使用最简单的代码,具有与持续时间转换相同的误导性语义:https://golang.org/pkg/time/#Duration

  

秒:= 10

     

fmt.Print(time.Duration(seconds)* time.Second)//打印10s

答案 3 :(得分:4)

Go的类型为Duration很高兴-明确定义单位可以防止实际问题。

并且由于Go严格的类型规则,您不能将持续时间乘以整数-您必须使用强制转换来乘法常见类型。 / p>

/*
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'
}

official documentation演示使用方法1:

  

要将整数单位转换为持续时间,请乘以:

seconds := 10
fmt.Print(time.Duration(seconds)*time.Second) // prints 10s

但是,当然,将持续时间乘以持续时间应该不会产生持续时间-从表面上看这是荒谬的。例如,5毫秒乘以5毫秒将生成6h56m40s。尝试平方5秒会导致溢出(如果使用常量完成甚至不会编译)。

顺便说一下,int64的{​​{1}}表示(以纳秒为单位"limits the largest representable duration to approximately 290 years"),这表明DurationDuration一样被处理作为一个有符号的值: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,所以在int64int64之间进行强制转换是明智的否定操作-必需仅满足有关混合类型的语言规则,并且对后续的乘法运算没有影响。

如果您出于纯洁的原因不喜欢转换,请将其埋入如上所示的函数调用中。

答案 4 :(得分:0)

轮到我了

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)
}

这有助于记住一个简单的事实,即时间。时间长度仅为int64,保持纳秒值。

这样,时间转换就变成了时间。只要记住:

  • int64
  • 总是纳秒

答案 5 :(得分:-2)

用于将变量乘以时间。其次使用以下代码

    oneHr:=3600
    addOneHrDuration :=time.Duration(oneHr)
    addOneHrCurrTime := time.Now().Add(addOneHrDuration*time.Second)