Para testar goroutines simultâneos, adicionei uma linha a uma função para fazer com que demorasse um tempo aleatório para retornar (até um segundo)
time.Sleep(rand.Int31n(1000) * time.Millisecond)
No entanto, quando compilei, recebi este erro
. \ crawler.go: 49: operação inválida: rand.Int31n (1000) * time.Millisecond (tipos incompatíveis int32 e time.Duration)
Alguma ideia? Como posso multiplicar uma duração?
rand.Seed(time.Now().Unix())
time.Sleep(time.Second * 2)
Duration
*Duration
=Duration
, em vez da original que realmente faz mais sentido:Duration
*int
=Duration
.int64(...) * Duration
faz muito mais sentido do que lançar paraDuration
, o que é apenas uma violação básica de como as unidades devem funcionar. Infelizmente isso não funciona. Você realmente tem que fazer oDuration * Duration
que é horrível.Você precisa convertê-lo para o formato correto Playground.
Se você verificar a documentação para suspensão , verá que ela requer
func Sleep(d Duration)
duração como parâmetro. Seu rand.Int31n retornaint32
.A linha do exemplo funciona (
time.Sleep(100 * time.Millisecond)
) porque o compilador é inteligente o suficiente para entender que aqui sua constante 100 significa uma duração. Mas se você passa uma variável, deve convertê-la.fonte
No Go, você pode multiplicar variáveis do mesmo tipo, portanto, você precisa ter as duas partes da expressão do mesmo tipo.
A coisa mais simples que você pode fazer é converter um número inteiro para a duração antes da multiplicação, mas isso violaria a semântica da unidade. O que seria multiplicação de duração por duração em termos de unidades?
Eu prefiro converter o tempo. Milissegundo em um int64 e, em seguida, multiplique-o pelo número de milissegundos e, em seguida, faça a conversão para o tempo.
Dessa forma, pode-se dizer que qualquer parte da expressão possui um valor significativo de acordo com seu tipo.
int64(time.Millisecond)
parte é apenas um valor sem dimensão - o número de menores unidades de tempo no valor original.Se seguir um caminho um pouco mais simples:
A parte esquerda da multiplicação é um absurdo - um valor do tipo "time.Duration", mantendo algo irrelevante para o seu tipo:
E não é apenas semântica, há uma funcionalidade real associada aos tipos. Este código imprime:
Curiosamente, o exemplo de código aqui usa o código mais simples, com a mesma semântica enganosa da conversão de Duração: https://golang.org/pkg/time/#Duration
fonte
É bom que o Go tenha um
Duration
tipo - ter unidades explicitamente definidas pode evitar problemas do mundo real.E, devido às regras estritas de Go, você não pode multiplicar uma Duração por um número inteiro - você deve usar uma conversão para multiplicar tipos comuns.
A documentação oficial demonstra o uso do método 1:
Mas, é claro, multiplicar uma duração por uma duração não deve produzir uma duração - isso não faz sentido. Caso em questão, 5 milissegundos vezes 5 milissegundos produz
6h56m40s
. Tentar quadrado 5 segundos resulta em um estouro (e nem será compilado se for feito com constantes).A propósito, a
int64
representaçãoDuration
em nanossegundos "limita a maior duração representável a aproximadamente 290 anos" , e isso indica queDuration
, assimint64
, é tratado como um valor assinado:(1<<(64-1))/(1e9*60*60*24*365.25) ~= 292
e é exatamente assim que é implementado:Portanto, porque sabemos que a representação subjacente de
Duration
é umint64
, executando o elenco entreint64
eDuration
é um NO-OP sensível - necessário apenas para satisfazer as regras de linguagem sobre tipos de mistura, e não tem efeito na operação de multiplicação subsequente.Se você não gostar do elenco por razões de pureza, enterre-o em uma chamada de função, como mostrei acima.
fonte
Para multiplicação da variável em time.Second usando o seguinte código
fonte
time.Duration
variáveis do Go . Você nomeia sua variáveladdOneHrDuration
de tempo,time.Duration
mas depois define-a para 3600 ns e não para uma hora. Atime.Duration
possui unidades básicas de nanossegundos. Para obter uma duração de uma hora, você pode fazer algo como:const oneHourDuration = 60 * time.Hour
(ou3600 * time.Second
outime.Hour
).