Goでスリープしようとしてハマった
Pythonでスリープするときは
import time time.sleep(1) # 1秒待つ time.sleep(0.5) # 0.5秒待つ
こうすれば良いが、同じ感覚でGoでスリープしようとしたらうまくいかなかった。
import "time" time.Sleep(1) // 1秒待つ(?)
どうなるかというと、やけに早く戻ってきてしまうのである。
ちなみに、こっちをやるとコンパイルエラーになってしまう。
time.Sleep(0.5) // constant 0.5 truncated to integer
Goのtime.Sleepの引数はDurationという型
https://golang.org/pkg/time/#Sleep
golangのドキュメントを見ると、time.Sleepの引数にはtime.Durationという型を受け付ける。
そして、time.Durationはint64の別名型らしい。
type Duration int64
A Duration represents the elapsed time between two instants as an int64 nanosecond count.
しかもナノ秒が基礎なので、time.Sleep(1)とやってしまうとたった1ナノ秒しか待たないことになる。
どうりで思ったより早く戻ってくるわけだ。
正式なN秒スリープの仕方
N秒スリープするのに正式も自己流も無いと思うが、以下の書き方が安定的である。
time.Sleep(1 * time.Second) // 1秒待つ
先ほど書いた通り、0.5秒待つときにこれはできない。
time.Sleep(0.5 * time.Second) // これはエラー(floatと掛け算できない) constant 0.5 truncated to integer
こうすれば動く。
time.Sleep(500 * time.Millisecond) // 0.5秒待つときはMillisecondと乗算する
ちなみにこれも動く。
var s time.Duration s = 5 time.Sleep(100 * s * time.Millisecond)
しかし、こっちは動かない。int64が掛け算の式に混入するのがダメらしい。
var s int64 // この他、float64もintも試したがダメだった s = 5 time.Sleep(100 * s * time.Millisecond) // invalid operation: 100 * s * time.Millisecond (mismatched types int64 and time.Duration)
どうしてもintと掛け算したい場合はこのように一度整数からDurationを作ってから掛け算する。
var t int t = 5 time.Sleep(time.Duration(t*100) * time.Millisecond) fmt.Println("Hello, world.")
なぜ、こんなことを調べ始めたかというと、「ランダムに数百ミリ秒待つ」という処理を書こうとしてハマったからである。
(続く)