継続時間に整数を掛ける方法は?


284

同時ゴルーチンをテストするために、関数に行を追加して、返されるまでにランダムな時間がかかるようにしました(最大1秒)。

time.Sleep(rand.Int31n(1000) * time.Millisecond)

しかし、コンパイルすると、このエラーが発生しました

。\ crawler.go:49:無効な操作:rand.Int31n(1000)* time.Millisecond(不一致タイプint32とtime.Duration)

何か案は?どうすれば期間を乗算できますか?

回答:


430

int32time.Duration異なるタイプです。あなたは、変換する必要があるint32time.Durationのような、time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond)


5
うまくいきました。私はまた、乱数ジェネレータを播種について学んだrand.Seed(time.Now().Unix())
大佐がパニック

44
私の知識のためだけに、次はどのように機能しますか? time.Sleep(time.Second * 2)
Ishan Khare 2015

59
定数は、使用方法に基づいて適応型を持っているため、機能します。詳細については、Rob Pikeによる次のブログ投稿をご覧ください。blog.golang.org
mna

28
これは、単純化した型システム(この場合は演算子のオーバーロードの欠如)が原因で奇妙なことの1つです- 実際に意味のある元の乗算ではなく、乗算をDuration* Duration= にキャストする必要がありますDurationDuration* int= Duration
Timmmm 2016年

14
まあ、演算子のオーバーロードまたは暗黙的な数値変換のどちらでもこれは機能します。暗黙の数値変換を省略しても問題はなかったと思います。これを振り返るint64(...) * DurationDuration、へのキャストよりも理にかなっています。これは、ユニットがどのように機能するかの基本的な違反です。残念ながらそれはうまくいきません。あなたは本当にDuration * Duration恐ろしいことをしなければなりません。
Timmmm 2016

59

正しい形式にキャストする必要がありますPlayground

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

ドキュメントのsleepを確認するとfunc Sleep(d Duration)、パラメータとして期間が必要であることがわかります。あなたのrand.Int31nを返しますint32

この例の行は機能します(time.Sleep(100 * time.Millisecond))。これは、ここで定数 100が期間を意味することをコンパイラーが理解できるほど賢いためです。ただし、変数を渡す場合は、キャストする必要があります。


16

Goでは、同じ型の変数を乗算できるため、式の両方の部分を同じ型にする必要があります。

あなたができる最も簡単なことは、乗算する前に整数を期間にキャストすることですが、それはユニットのセマンティクスに違反します。期間の単位による期間の乗算はどうなりますか?

私はむしろtime.Millisecondをint64に変換し、それをミリ秒の数で乗算してから、time.Durationにキャストします。

time.Duration(int64(time.Millisecond) * int64(rand.Int31n(1000)))

このように、式のどの部分も、そのタイプに応じて意味のある値を持つと言えます。int64(time.Millisecond)部分は、無次元の値です-元の値の時間の最小単位の数。

少し簡単な道を歩く場合:

time.Duration(rand.Int31n(1000)) * time.Millisecond

乗算の左側はナンセンスです-「time.Duration」型の値で、その型とは無関係の何かを保持しています:

numberOfMilliseconds := 100
// just can't come up with a name for following:
someLHS := time.Duration(numberOfMilliseconds)
fmt.Println(someLHS)
fmt.Println(someLHS*time.Millisecond)

そして、それは単なる意味論ではなく、型に関連付けられた実際の機能があります。このコードは出力します:

100ns
100ms

興味深いことに、ここのコードサンプルは、最も単純なコードを使用しており、Duration変換と同じ誤解を招くようなセマンティクスを持っていますhttps : //golang.org/pkg/time/#Duration

秒:= 10

fmt.Print(time.Duration(seconds)* time.Second)// 10秒を出力します


5

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

公式ドキュメントは、メソッド#1を使用して示しています。

整数の単位を期間に変換するには、以下を乗算します。

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

ただし、もちろん、期間に期間を乗算しても、期間は生成されません。これは、一見無意味です。その例として、5ミリ秒に5ミリ秒を掛けたものがが生成され6h56m40sます。5秒を2乗しようとすると、オーバーフローが発生します(定数を使用してコンパイルしてもコンパイルされません)。

ちなみに、ナノ秒単位のint64表現はDuration「表現可能な最大期間を約290年に制限します」。これはDuration、がのようint64に、符号付きの値として扱われることを示しています。(1<<(64-1))/(1e9*60*60*24*365.25) ~= 292これは、実装方法とまったく同じです。

// A Duration represents the elapsed time between two instants
// as an int64 nanosecond count. The representation limits the
// largest representable duration to approximately 290 years.
type Duration int64

したがって、の基礎となる表現はDurationでありint64、の間int64でキャストを実行しDuration、賢明なNO-OP であることがわかっているため、型の混合に関する言語規則を満たすためにのみ必要であり、後続の乗算演算には影響しません。

純粋さの理由でキャストが気に入らない場合は、上で示したように関数呼び出しに埋め込んでください。


「一般的な型として/と乗算」。
nobar

ここでの(間違った)回答での除算に関する同様の議論。
nobar

-3

変数から時間への乗算。次のコードを使用して2番目

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

これはGoのtime.Duration変数を使用する良い方法ではありません。addOneHrDuration時間の変数に名前を付けてtime.Durationから、それを1時間ではなく3600 nsに設定します。Aはtime.Durationたまたまナノ秒の基本単位を持っています。実際に1時間の期間を取得するには、次のようにしますconst oneHourDuration = 60 * time.Hour(または3600 * time.Secondまたはtime.Hour)。
Dave C
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.