Goに「goto」ステートメントがあることに驚いた。「goto」ステートメントは過去のものであり、プログラムの実際のフローを妨げるため悪であり、関数またはメソッドは常にフローを制御するためのより良い方法であると私は常に教えられてきました。
私は何かが欠けているに違いありません。なぜグーグルはそれを含めたのですか?
Go標準ライブラリのソースコードを実際にチェックすると、goto
sが実際に適切に適用されている場所を確認できます。
たとえば、math/gamma.go
ファイルでは、次のgoto
ステートメントが使用されます。
for x < 0 {
if x > -1e-09 {
goto small
}
z = z / x
x = x + 1
}
for x < 2 {
if x < 1e-09 {
goto small
}
z = z / x
x = x + 1
}
if x == 2 {
return z
}
x = x - 2
p = (((((x*_gamP[0]+_gamP[1])*x+_gamP[2])*x+_gamP[3])*x+_gamP[4])*x+_gamP[5])*x + _gamP[6]
q = ((((((x*_gamQ[0]+_gamQ[1])*x+_gamQ[2])*x+_gamQ[3])*x+_gamQ[4])*x+_gamQ[5])*x+_gamQ[6])*x + _gamQ[7]
return z * p / q
small:
if x == 0 {
return Inf(1)
}
return z / ((1 + Euler*x) * x)
}
このgoto
場合、最後にチェックされる、制御フローのためだけに使用される別の(ブール)変数を導入する必要がなくなります。この場合、goto
ステートメントはコードを実際に読みやすくし、従うのを容易にします(goto
あなたが言及した反対の議論とはまったく反対です)。
また、goto
ステートメントには非常に特殊なユースケースがあることに注意してください。gotoの言語仕様では、スコープに入ってくる(宣言されている)変数を飛び越えたり、他の(コード)ブロックに飛び込んだりすることはできないと規定されています。
Gotoは、組み込みの制御機能のいずれも目的どおりに機能しない場合、およびGotoを使用して目的を表現できる場合に適しています。(これらの場合、gotoがない言語では、残念です。最終的に、制御機能を悪用したり、ブールフラグを使用したり、gotoよりも悪い他のソリューションを使用したりします。)
他の制御機能(かなり明白な方法で使用される)が必要なことを実行できる場合は、gotoよりも優先して使用する必要があります。そうでない場合は、太字にしてgotoを使用してください。
最後に、Goのgotoには、いくつかのあいまいなバグを回避するように設計されたいくつかの制限があることに注意してください。仕様のこれらの制限を参照してください。
後藤文は、60年代と70年代のスパゲッティコードの時代以来、多くの信用を失っています。当時、ソフトウェア開発の方法論は非常に貧弱でした。ただし、後藤は本来悪ではありませんが、もちろん、怠惰なプログラマーや熟練していないプログラマーによって悪用されたり悪用されたりする可能性があります。悪用されたGotoに関する多くの問題は、チームコードレビューなどの開発プロセスで解決できます。
goto
continue
、、break
およびと同じ技術的な方法でジャンプしreturn
ます。これらは同じように悪であると主張することができますが、そうではありません。
GoチームがGotosを含めた理由は、おそらくそれが一般的なフロー制御プリミティブであるという事実によるものです。さらに、彼らは、Goの範囲は、ばかげた安全な言語を悪用できないようにすることを除外していると結論付けたと思います。