Para probar goroutines concurrentes, agregué una línea a una función para hacer que regrese un tiempo aleatorio (hasta un segundo)
time.Sleep(rand.Int31n(1000) * time.Millisecond)
Sin embargo, cuando compilé, recibí este error
. \ crawler.go: 49: operación no válida: rand.Int31n (1000) * time.Millisecond (tipos no coincidentes int32 y time.Duration)
¿Algunas ideas? ¿Cómo puedo multiplicar una duración?
rand.Seed(time.Now().Unix())
time.Sleep(time.Second * 2)
Duration
*Duration
=Duration
, en lugar de la original, que en realidad tiene más sentido:Duration
*int
=Duration
.int64(...) * Duration
tiene mucho más sentido que lanzarDuration
, lo cual es solo una violación básica de cómo deberían funcionar las unidades. Lamentablemente eso no funciona. Realmente tienes que hacer loDuration * Duration
que es horrible.Tienes que enviarlo a un formato correcto Playground.
Si verificará la documentación para dormir , verá que requiere una
func Sleep(d Duration)
duración como parámetro. Tu rand.Int31n regresaint32
.La línea del ejemplo funciona (
time.Sleep(100 * time.Millisecond)
) porque el compilador es lo suficientemente inteligente como para comprender que aquí su constante 100 significa una duración. Pero si pasa una variable, debe lanzarla.fuente
En Go, puede multiplicar variables del mismo tipo, por lo que debe tener ambas partes de la expresión del mismo tipo.
Lo más simple que puedes hacer es lanzar un número entero a la duración antes de multiplicar, pero eso violaría la semántica de la unidad. ¿Cuál sería la multiplicación de la duración por la duración en términos de unidades?
Prefiero convertir el tiempo. Milisegundos a un int64, y luego multiplicarlo por el número de milisegundos, luego emitir a tiempo. Duración:
De esta manera, se puede decir que cualquier parte de la expresión tiene un valor significativo de acuerdo con su tipo.
int64(time.Millisecond)
parte es solo un valor adimensional: el número de unidades de tiempo más pequeñas en el valor original.Si camina por un camino un poco más simple:
La parte izquierda de la multiplicación no tiene sentido, un valor de tipo "tiempo. Duración", que contiene algo irrelevante para su tipo:
Y no se trata solo de semántica, hay una funcionalidad real asociada con los tipos. Este código imprime:
Curiosamente, el ejemplo de código aquí usa el código más simple, con la misma semántica engañosa de conversión de Duración: https://golang.org/pkg/time/#Duration
fuente
Es bueno que Go tenga un
Duration
tipo: tener unidades definidas explícitamente puede prevenir problemas del mundo real.Y debido a las estrictas reglas de tipo de Go, no puedes multiplicar una Duración por un entero; debes usar un yeso para multiplicar los tipos comunes.
La documentación oficial demuestra el uso del método 1:
Pero, por supuesto, multiplicar una duración por una duración no debería producir una duración, eso no tiene sentido a primera vista. Caso en cuestión, produce 5 milisegundos por 5 milisegundos
6h56m40s
. Intentar cuadrar 5 segundos resulta en un desbordamiento (y ni siquiera se compilará si se hace con constantes).Por cierto, la
int64
representaciónDuration
en nanosegundos "limita la mayor duración representable a aproximadamente 290 años" , y esto indica queDuration
, comoint64
, se trata como un valor con signo:(1<<(64-1))/(1e9*60*60*24*365.25) ~= 292
y así es exactamente como se implementa:Entonces, porque sabemos que la representación subyacente de
Duration
es unint64
, realizando el reparto entreint64
yDuration
es un NO-OP sensible, requerido solo para satisfacer las reglas del lenguaje sobre la mezcla de tipos, y no tiene ningún efecto en la operación de multiplicación posterior.Si no le gusta el casting por razones de pureza, entiérrelo en una llamada a la función como he mostrado anteriormente.
fuente
Para la multiplicación de variable a tiempo. Segundo usando el siguiente código
fuente
time.Duration
variables de Go . Usted nombra su variableaddOneHrDuration
de tiempotime.Duration
pero luego procede a configurarla en 3600 ns, no en una hora. Atime.Duration
tiene unidades base de nanosegundos. Para obtener realmente una duración de una hora, puede hacer algo como:const oneHourDuration = 60 * time.Hour
(o3600 * time.Second
otime.Hour
).