Um gleichzeitige Goroutinen zu testen, habe ich einer Funktion eine Zeile hinzugefügt, damit die Rückkehr eine zufällige Zeit in Anspruch nimmt (bis zu einer Sekunde).
time.Sleep(rand.Int31n(1000) * time.Millisecond)
Beim Kompilieren wurde jedoch dieser Fehler angezeigt
. \ crawler.go: 49: ungültige Operation: rand.Int31n (1000) * time.Millisecond (nicht übereinstimmende Typen int32 und time.Duration)
Irgendwelche Ideen? Wie kann ich eine Dauer multiplizieren?
rand.Seed(time.Now().Unix())
time.Sleep(time.Second * 2)
Duration
*Duration
= setzenDuration
, anstatt auf die ursprüngliche, die tatsächlich sinnvoller ist:Duration
*int
=Duration
.int64(...) * Duration
ist das viel sinnvoller als das CastingDuration
, was nur eine grundlegende Verletzung der Funktionsweise von Einheiten darstellt. Leider funktioniert das nicht. Sie müssen wirklich tun,Duration * Duration
was schrecklich ist.Sie müssen es in ein korrektes Format umwandeln Playground.
Wenn Sie die Dokumentation auf Schlaf prüfen , sehen Sie, dass die
func Sleep(d Duration)
Dauer als Parameter erforderlich ist. Ihr rand.Int31n kehrt zurückint32
.Die Zeile aus dem Beispiel funktioniert (
time.Sleep(100 * time.Millisecond)
), weil der Compiler klug genug ist, um zu verstehen, dass hier Ihre Konstante 100 eine Dauer bedeutet. Wenn Sie jedoch eine Variable übergeben, sollten Sie sie umwandeln.quelle
In Go können Sie Variablen desselben Typs multiplizieren, sodass beide Teile des Ausdrucks denselben Typ haben müssen.
Das Einfachste, was Sie tun können, ist, vor dem Multiplizieren eine Ganzzahl in die Dauer umzuwandeln. Dies würde jedoch die Einheitensemantik verletzen. Was wäre eine Multiplikation von Dauer mit Dauer in Einheiten?
Ich würde lieber time.Millisecond in int64 konvertieren und es dann mit der Anzahl der Millisekunden multiplizieren und dann in time umwandeln. Duration:
Auf diese Weise kann gesagt werden, dass jeder Teil des Ausdrucks je nach Typ einen aussagekräftigen Wert hat.
int64(time.Millisecond)
Teil ist nur ein dimensionsloser Wert - die Anzahl der kleinsten Zeiteinheiten im ursprünglichen Wert.Wenn Sie einen etwas einfacheren Weg gehen:
Der linke Teil der Multiplikation ist Unsinn - ein Wert vom Typ "time.Duration", der etwas enthält, das für seinen Typ irrelevant ist:
Und es ist nicht nur Semantik, es gibt tatsächliche Funktionen, die mit Typen verbunden sind. Dieser Code druckt:
Interessanterweise verwendet das Codebeispiel hier den einfachsten Code mit derselben irreführenden Semantik der Dauerkonvertierung: https://golang.org/pkg/time/#Duration
quelle
Es ist schön, dass Go einen
Duration
Typ hat - explizit definierte Einheiten können reale Probleme verhindern.Und aufgrund der strengen Typregeln von Go können Sie eine Dauer nicht mit einer Ganzzahl multiplizieren. Sie müssen eine Umwandlung verwenden, um allgemeine Typen zu multiplizieren.
Die offizielle Dokumentation zeigt die Verwendung von Methode 1:
Aber das Multiplizieren einer Dauer mit einer Dauer sollte natürlich keine Dauer ergeben - das ist auf den ersten Blick unsinnig. In diesem Fall werden 5 Millisekunden mal 5 Millisekunden erzeugt
6h56m40s
. Der Versuch, 5 Sekunden zu quadrieren, führt zu einem Überlauf (und wird nicht einmal kompiliert, wenn Konstanten verwendet werden).Übrigens begrenzt die
int64
DarstellungDuration
in Nanosekunden "die größte darstellbare Dauer auf ungefähr 290 Jahre" , und dies zeigt an, dassDuration
wieint64
ein vorzeichenbehafteter Wert behandelt wird:(1<<(64-1))/(1e9*60*60*24*365.25) ~= 292
und genau so wird es implementiert:Also, weil wir wissen, dass die zugrunde liegende Darstellung von
Duration
einint64
ist, das Casting zwischenint64
undDuration
ein vernünftiges NO-OP ist - nur erforderlich, um Sprachregeln über das Mischen von Typen zu erfüllen, und es hat keine Auswirkung auf die nachfolgende Multiplikationsoperation.Wenn Ihnen das Casting aus Gründen der Reinheit nicht gefällt, begraben Sie es in einem Funktionsaufruf, wie ich oben gezeigt habe.
quelle
Zur Multiplikation der Variablen mit der Zeit. Zweitens mit folgendem Code
quelle
time.Duration
Variablen von Go zu verwenden . Sie nennen Ihre VariableaddOneHrDuration
Zeit ,time.Duration
aber dann gehen sie nicht zu einer Stunde auf 3600 ns einzustellen. A hattime.Duration
zufällig Basiseinheiten von Nanosekunden. Um tatsächlich eine Stunde zu erhalten, können Sie Folgendes tun:const oneHourDuration = 60 * time.Hour
(oder3600 * time.Second
odertime.Hour
).