Pour tester des goroutines simultanées, j'ai ajouté une ligne à une fonction pour qu'elle prenne un temps aléatoire pour revenir (jusqu'à une seconde)
time.Sleep(rand.Int31n(1000) * time.Millisecond)
Cependant, quand j'ai compilé, j'ai eu cette erreur
. \ crawler.go: 49: opération non valide: rand.Int31n (1000) * time.Millisecond (types incompatibles int32 et time.Duration)
Des idées? Comment puis-je multiplier une durée?
rand.Seed(time.Now().Unix())
time.Sleep(time.Second * 2)
Duration
*Duration
=Duration
, au lieu de l'original qui a en fait plus de sens:Duration
*int
=Duration
.int64(...) * Duration
beaucoup plus de sens que de lancerDuration
, ce qui n'est qu'une violation de base du fonctionnement des unités. Malheureusement, cela ne fonctionne pas. Vous devez vraiment faire ceDuration * Duration
qui est horrible.Vous devez le convertir dans un format correct Playground.
Si vous vérifiez la documentation pour le sommeil , vous voyez qu'elle nécessite la
func Sleep(d Duration)
durée comme paramètre. Votre rand.Int31n revientint32
.La ligne de l'exemple fonctionne (
time.Sleep(100 * time.Millisecond)
) car le compilateur est suffisamment intelligent pour comprendre qu'ici votre constante 100 signifie une durée. Mais si vous passez une variable, vous devez la transtyper.la source
Dans Go, vous pouvez multiplier les variables du même type, vous devez donc avoir les deux parties de l'expression du même type.
La chose la plus simple que vous puissiez faire est de convertir un entier en durée avant de le multiplier, mais cela violerait la sémantique des unités. Quelle serait la multiplication de la durée par la durée en terme d'unités?
Je préfère convertir time.Millisecond en int64, puis le multiplier par le nombre de millisecondes, puis transtypé en time.
De cette façon, n'importe quelle partie de l'expression peut être considérée comme ayant une valeur significative selon son type.
int64(time.Millisecond)
partie est juste une valeur sans dimension - le nombre de plus petites unités de temps dans la valeur d'origine.Si vous suivez un chemin un peu plus simple:
La partie gauche de la multiplication est un non-sens - une valeur de type "time.Duration", contenant quelque chose de non pertinent pour son type:
Et ce n'est pas seulement de la sémantique, il y a des fonctionnalités réelles associées aux types. Ce code imprime:
Fait intéressant, l'exemple de code ici utilise le code le plus simple, avec la même sémantique trompeuse de conversion de durée: https://golang.org/pkg/time/#Duration
la source
C'est bien que Go ait un
Duration
type - avoir des unités explicitement définies peut éviter des problèmes du monde réel.Et en raison des règles de type strictes de Go, vous ne pouvez pas multiplier une durée par un entier - vous devez utiliser un cast pour multiplier les types communs.
La documentation officielle montre l'utilisation de la méthode # 1:
Mais, bien sûr, multiplier une durée par une durée ne devrait pas produire une durée - c'est absurde à première vue. Par exemple, 5 millisecondes multipliées par 5 millisecondes
6h56m40s
. Tenter de mettre au carré 5 secondes entraîne un débordement (et ne sera même pas compilé s'il est fait avec des constantes).Soit dit en passant, la
int64
représentationDuration
en nanosecondes "limite la plus grande durée représentable à environ 290 ans" , et cela indique queDuration
, commeint64
, est traité comme une valeur signée:,(1<<(64-1))/(1e9*60*60*24*365.25) ~= 292
et c'est exactement comme cela qu'il est mis en œuvre:Donc, parce que nous savons que la représentation sous-jacente de
Duration
est unint64
, effectuant la conversion entreint64
etDuration
est un NO-OP sensible - requis uniquement pour satisfaire les règles de langage sur les types de mélange, et cela n'a aucun effet sur l'opération de multiplication suivante.Si vous n'aimez pas le casting pour des raisons de pureté, enterrez-le dans un appel de fonction comme je l'ai montré ci-dessus.
la source
Pour la multiplication de la variable en temps, la seconde en utilisant le code suivant
la source
time.Duration
variables de Go . Vous nommez votre variableaddOneHrDuration
de temps,time.Duration
puis procédez à la définir à 3600 ns et non à une heure. Untime.Duration
arrive d'avoir des unités de base de nanosecondes. Pour obtenir une durée d'une heure, vous pouvez faire quelque chose comme:const oneHourDuration = 60 * time.Hour
(ou3600 * time.Second
outime.Hour
).