1. ホーム
  2. go

error is nil repetition のチェックをしないようにするか?

2023-10-06 10:05:12

質問

私は現在goを学んでおり、私のコードのいくつかは次のようになります。

a, err := doA()
if err != nil {
  return nil, err
}
b, err := doB(a)
if err != nil {
  return nil, err
}
c, err := doC(b)
if err != nil {
  return nil, err
}
... and so on ...

これは、エラーチェックがほとんどの行を占めているため、私にはちょっと間違っているように見えます。エラー処理を行うためのより良い方法はありますか?私はおそらくいくつかのリファクタリングでこれを避けることができますか?

UPDATEです。 たくさんのご回答ありがとうございました。私の例では、doBはaに依存し、doCはbに依存し、といった具合になることに注意してください。したがって、ほとんどの提案されたリファクタリングは、このケースでは動作しません。他の提案はありますか?

どのように解決するのですか?

これはよくある苦情ですが、これにはいくつかの回答があります。

ここでは、よくあるものをいくつか紹介します。

1 「そんなに悪くはない

これは、このような苦情に対する非常に一般的な反応です。あなたのコードに数行の余分なコードがあるという事実は、実際にはそれほど悪いことではありません。それはちょっとした安っぽいタイピングであり、読む側としては非常に扱いやすいものです。

2 - それは実際には良いことです

これは、これらの余分な行を入力し、読むことは、実際にあなたのロジックがその時点で逃げるかもしれないことを非常によく思い出させるという事実に基づいていますし、その前の行で配置したすべてのリソース管理を元に戻す必要があります。これは通常、例外との比較で取り上げられますが、例外は暗黙のうちにロジックの流れを壊してしまうので、開発者は常に隠れたエラーの経路を念頭に置くことを余儀なくされます。少し前に、私はこのことについてより深い戯言を書きました。 ここで .

3 - パニック/リカバリーを使う

特定の状況においては panic を既知の型とし、次に recover を使い、パッケージコードが世に出る直前にそれを適切なエラーに変換し、代わりにそれを返します。この手法は、(un) marshalers などの再帰的なロジックを展開するために最も一般的に使用されます。

私は個人的に、ポイント 1 と 2 により密接に関連するため、これをあまり乱用しないように努めています。

4 - コードを少し再編成する

状況によっては、繰り返しを避けるために、ロジックを少し再編成することができます。

些細な例として、これ。

err := doA()
if err != nil {
    return err
}
err := doB()
if err != nil {
    return err
}
return nil

のように整理することもできる。

err := doA()
if err != nil {
    return err
}
return doB()

5 - 名前付きの結果を使用する

returnステートメントからerr変数を取り除くために、名前付き結果を使用する人がいます。なぜなら、ほとんど節約にならず、コードの明快さが失われ、1つ以上の結果が救済のためのreturn文の前に定義されると、ロジックが微妙な問題に陥りやすくなるからです。

6 - if条件の前にステートメントを使用する

Tom Wildeが下のコメントでよく言っていた通りです。 if 文は は単純なステートメントを受け入れる を条件の前に置くことができます。だから、こんなことができる。

if err := doA(); err != nil {
    return err
}

これは立派なGoイディオムで、よく使われます。

いくつかの具体的なケースでは、わかりやすくするために、この方法でステートメントを埋め込むことだけは避けたいのですが、これは微妙に個人的なことです。