1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Go 言語の do-while 、あるいはリトライ処理

Last updated at Posted at 2025-01-31

golang do-while でぐぐると

C の

hoge.c
do {
    ループしたい処理
} while (cond);

をどう書くのがいいのかなって golang do-while でぐぐってみると、だいたい

hoge.go
for {
    ループしたい処理
    if !cond {
        break
    }
}

って書き方が出てきて微妙な気分になるのだが、Go の場合

hoge.go
for func() bool {
    ループしたい処理
    return cond
}() {
}

でもいいんじゃないっすかね。一見しただけでは do-while だと分かりにくいのが玉に瑕。

リトライ処理

ところで、こういうフローが必要になる場合ってだいたいがリトライ処理なのだが、困ったことにリトライ処理を書く場合には do-while でも微妙に痒いところに手が届かなくて、C でも

hoge.c
for (;;) {
    ここで複雑な処理
    if (!needRetry) break;
    log("リトライすっぺ");
    awesomesleep(interval);
    interval += interval;  // exponential backoff
}

って書くのもなんだしなあと結局

hoge.c
retry:
    ここで複雑な処理
    if (needRetry) {
        log("リトライすっぺ");
        awesomesleep(interval);
        interval += interval;  // exponential backoff
        goto retry;
    }

みたいに goto 使って書いたりするのだが、上の書き方なら

hoge.go
for func() bool {
    ここで複雑な処理
    if errors.Is(err, tempBusy) {
        return true // リトライするよ
    } else {
        return false // リトライしないよ
    }
}() {
    log("リトライすっぺ")
    awesomesleep(interval)
    interval += interval  // exponential backoff
}

という風に書けるし、goto が要らなくなってダイクストラ師もニッコリ。

注意点

単なるループとは return や defer の振る舞いが変わる点だけは注意な。もっとも、defer に関しては、ループの中で defer 使うのはだいたいアンチパターンだし、むしろ func で括ることにより「ループが回るたびに毎回 defer が実行されて便利」まであるのでデメリットとも言い難い。return の方はマジ不便な場合もあるので、その時はしょうがないので「無限 for ループを if で break する方」を選ぶなりなんなりしてくらはい。
あとは毎回関数呼び出しされるオーバーヘッドとかあるけど、それが気になる人は Go 使わんでしょ(暴言)。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?