私はC言語を書く際に結構GOTO文を使う人なのですが、
最初に働いた会社では、先輩にGOTOはあまり使うもんじゃないと諭されたものです。
※新人教育の一環としては正しい
そんな私も熟練のC言語プログラマ(2016年度に書いたCプログラムはごく少数です(ㅍ_ㅍ)
どういうケースでGOTOを使っているのか経験を踏まえて列挙してみました。
ネストループからの脱出
フラグ使ってbreakを繰り返すよりスマートに書けます
for (;;) {
for (;;) {
if (a==b) {
goto out;
}
}
}
out:
エラー処理やリソース解放を末尾にまとめる
リソース確保/解放相当の処理を必ず行わなければならない場合なんかによくやる処理です。
Golangのdefer文やモダンなC++のdestoctorがほしいです。
if (xxx) {
goto err1;
}
if (xxx) {
goto err2;
}
err2:
//リソース解放2
err1:
//リソース解放1
return ret;
}
長い事前処理のskip
事前処理を関数化すると見栄えが良くないし、
ネストが浅くフラットに関数全体を見渡しやすくする場合なんかに使います。
if () {
goto skip;
}
...
...
...
skip:
//メイン処理開始
...
パラメータリセットしてretry
リトライ回数が決まっており、かつ初期化パラメータなんかが変動する場合を
簡潔に書きたい場合に使います。
r=0
retry:
a=0;
for (;;) {
if (;;) {
r++;
goto retry;
}
}
フラグの代わりにif()thenにjump
このパターンは正直な話、1-2度くらいしか書いたことがないのですが、
linux kernelをgotoでgrepすると結構頻出するなーってことで紹介です。
基本的にはネストが深くない、フラットな構造を維持しつつ謎なフラグを減らしたいのだと考えます。
...
if (first) goto then;
...
...
if (first) {
then:
...
...
} else {
}
まとめ
ダジャレでタイトルとか変える人は高頻度でおっさんです、私もおっさんな歳で感慨深い。
アンチGOTOに負けず、必要な個所でガンガンGOTOを使っていきましょう!