为了测试并发的goroutine,我在函数中添加了一行代码,以使其花费随机的时间返回(最多一秒钟)。
出现此错误


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


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

#1 楼

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

评论


就我所知,接下来的工作原理是什么? time.Sleep(time.Second * 2)

– Ishan Khare
15年8月27日在13:25



之所以起作用,是因为常量根据其使用方式具有自适应类型。请参阅Rob Pike撰写的此博客文章,其中对其进行了详细说明:blog.golang.org/constants

–mna
15年8月28日在14:12

由于其简单的类型系统(在这种情况下没有操作员重载),这是一件很奇怪的事情-您必须将乘法转换为Duration * Duration = Duration,而不是原来的乘积真正有意义: * int =持续时间。

– Timmmm
16年5月5日在14:49

那么,无论是运算符重载还是隐式数值转换都可以使此工作有效。我认为将隐式数值转换排除在外是正确的。回过头看一下int64(...)*持续时间比强制转换为Duration更有意义,这只是对单元工作方式的基本违反。可悲的是这不起作用。您真的必须要做持续时间*可怕的持续时间。

– Timmmm
16年7月21日在12:22

这太可怕了。即使可以,也绝不建议在C中将time_t乘以time_t。这不仅是一个简单的类型系统,而且是令人困惑和可怕的API设计。

–lilydjwg
18年1月23日在15:24

#2 楼

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

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



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

示例中的行有效(time.Sleep(100 * time.Millisecond)),因为编译器足够聪明,可以理解这里的常数100表示​​持续时间。但是,如果传递变量,则应将其强制转换。

评论


很好,但是为什么可以将Duration乘以原始整数(不在变量中),例如:time.Sleep(100 * time.Millisecond)AFAIK,100不是Duration

–carnicer
20年7月5日,12:01



#3 楼

在Go中,您可以将相同类型的变量相乘,因此需要使表达式的两个部分都具有相同类型。
最简单的操作是在乘法之前将整数强制转换为持续时间,但这会违反单位语义。持续时间乘以持续时间的单位是什么?
我宁愿将time.Millisecond转换为int64,然后将其乘以毫秒数,然后转换为time。Duration:
time.Duration(int64(time.Millisecond) * int64(rand.Int31n(1000)))

通过这种方式,表达式的任何部分都可以说具有有意义的值。 int64(time.Millisecond)部分只是一个无量纲的值-原始值中最小的时间单位数。
如果走一条稍微简单的路径:类型为“ time.Duration”的东西,与它的类型无关:
time.Duration(rand.Int31n(1000)) * time.Millisecond

不只是语义,还有与类型相关的实际功能。
此代码打印:
numberOfMilliseconds := 100
// just can't come up with a name for following:
someLHS := time.Duration(numberOfMilliseconds)
fmt.Println(someLHS)
fmt.Println(someLHS*time.Millisecond)

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

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


#4 楼

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


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

顺便说一句,以纳秒为单位的int64Duration表示将最大可表示持续时间限制为大约290年”,这表明Durationint64一样被视为有符号值:(1<<(64-1))/(1e9*60*60*24*365.25) ~= 292,这就是它的实现方式:知道Duration的基本表示形式是int64,执行int64Duration之间的强制转换是明智的NO-OP -仅需要满足有关混合类型的语言规则,并且对后续的乘法运算没有影响。 >
如果出于纯度原因不喜欢这种类型的转换,请将其埋入如上所示的函数调用中。

评论


“与普通类型相乘”。

–布伦特·布拉德本(Brent Bradburn)
19年9月11日14:15在

此处有关(错误)答案的划分相关的类似讨论。

–布伦特·布拉德本(Brent Bradburn)
20-2-25在15:16

#5 楼

轮到我了:
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
总是纳秒


#6 楼

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

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


评论


这不是使用Go的time.Duration变量的好方法。您将变量addOneHrDuration命名为time.Duration时间,然后将其设置为3600 ns,而不是一小时。 time.Duration的基本单位为纳秒。要获得一个小时的持续时间,您可以执行以下操作:const oneHourDuration = 60 * time.Hour(或3600 * time.Second或time.Hour)。

–戴夫C
19年8月9日,11:11