Go
golang

[Go] 一定時間特定の処理を繰り返し行う

特定の処理をひとまとめにした関数を block とします。

1秒後に特定の処理をしたいとき、非同期処理でなければ time.Sleep(time.Second) を普通に使えば良いし、非同期処理であれば time.After(time.Second) を使って、

done := time.After(time.Second)

// todo
<-done
block()

とすれば良いでしょう1


しかし、1秒間に特定の処理を繰り返し行いたいときに使う関数が標準ライブラリの中に見当たらなかったので今回作ってみました。

func DuringFunc(d time.Duration, f func()) {

flg := true
go func() {
for flg {
f()
}
}()
time.Sleep(d)
flg = false
}

特に説明はいりませんね。

使い方は、

DuringFunc(time.Second, block)

といった感じです2

これにより例えば、最初にアクセスがあってから1秒間は連続するアクセスを受け付けるが、1秒経過後はアクセスを受け付けない、といったときに使えます。

もしかしたら自分の調査不足で標準ライブラリの中にそれらしい関数があるかもしれないので、知ってる方がいたらコメント欄でこっそり教えてください!

言うまでもないですが、1秒のところ(time.Second)を1以上の time.Duration 型の値に変えれば任意の一定時間特定の処理を繰り返し行うことができます。


【追記】2018/4/24

goroutine を 明示的に使わずに DuringFunc を作りたい場合は、

func DuringFunc(d time.Duration, f func()) {

done := time.After(time.Second)
for cond := true; cond; {
select {
case <-done:
cond = false
default:
f()
}
}
}

のようにもできますね。ただ select で受けない分、最初に示した DuringFunc のほうが早そうです。

https://wandbox.org/permlink/Uqe412Q7Fq8JqurS





  1. この書き方だと // todo が1秒以内に終了しなければいけません。もし終了しない場合は

    time.AfterFunc(time.Second, block) で頑張ってください。 



  2. 一般的に DuringFunc で実行した block の合計処理時間は1秒以上になります。つまり、最初の block を実行し始めてから1秒経過したときに実行している block の処理が完了するまで DuringFunc は return されません。