繁体   English   中英

如何将持续时间乘以 integer?

[英]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)

有任何想法吗? 我怎样才能乘以持续时间?

int32time.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 秒会导致溢出(如果使用常量完成,甚至不会编译)。

顺便说一句,以纳秒为单位的Durationint64表示“将最大可表示的持续时间限制为大约 290 年” ,这表明Durationint64一样,被视为有符号值: (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 ,在int64Duration之间执行转换是一个明智的 NO-OP —— 只需要满足关于混合类型的语言规则,它对后续的乘法运算没有影响.

如果您出于纯度的原因不喜欢铸造,请将其埋在函数调用中,如我上面所示。

对一些关于将DurationDuration相乘的评论和讨论感到困惑,我对单位和函数进行了一些尝试并得到了这个:

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使用。


我在这篇文章中写了这些细节。

Go 默认类型速查表

轮到我了:

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 变成了一种形式。 请记住:

  • int64
  • 总是纳秒

您也可以使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM