みなさん、こんにちは。魚のフライです。
Go言語の主な機能はエラーメカニズムであるため、基本的にすべてのエラー処理の提案またはディスカッションを確認して学習し、さまざまな思考の視野と解決策を開発します。
今日私が共有するのは、 @CristoGarcíaによって提案された「Go2の単純なエラー処理」という提案です。少し変更されています。Jianyuと学び、話し合いましょう。
GoはまだGoでなければなりません
この提案の核心は、Goは依然としてGoでなければならないということです。つまり、エラー処理の変換は次の原則を満たす必要があります。
- 可能な限り少ない構文を追加します。
- できるだけ明確で便利にしてください。
この記事の「私」は、私が学んでいる揚げ魚ではなく、提案者の@CristoGarcíaを指します。
オリジナルのアイデア
元の提案者@PeterRkは、次のアイデアを提案しました。
func getDivisorFromDB(key string) (uint, error) {
//...
}
func GetDivisor(key string) (uint, error) {
exit := func(err error) (uint, error) {
return 1, fmt.Errorf("fail to get divisor with key \"%s\": %v", key, err)
}
divisor := check(getDivisorFromDB(key), exit)
//...
return divisor, nil
}
复制代码
使用例:
divisor := check(getDivisorFromDB(key), exit)
复制代码
既存のものと同等:
divisor, err := getDivisorFromDB(key)
if err != nil {
return exit(err) //return err
}
复制代码
提案者はこれが正しい方向であると信じており、私たちはそれを改善することができます(含意:現在は十分ではありません)。
質問はなんですか
この元のアイデアには2つの問題があります。
- あいまいなreturnステートメントが含まれています。
- 抽象化が不要な場合があり、コードが読みにくくなります。
新しい考え
この新しいアイデアは上記の2つの問題を解決する必要があるため、@CristoGarcíaはより良い結果を達成することを望んでいます。構文を簡単に変更して、orキーワードを追加します。
次の例を取得できます。
divisor, err := getDivisorFromDB(key) or return exit(err)
复制代码
新しく追加されたorキーワードは、最後の戻り値(エラータイプである必要があります)がnilと異なるかどうかをチェックします。そうでない場合は、右側の関数が実行されます。
returnを省略しても、コードは実行を継続します。通常のGoコードと同様に破棄されるため、関数はより再利用可能です。
次の例:
func GetDivisor(key string) (divisor uint, err error) {
divisor, err = getDivisorFromDB(key) or return
return
}
复制代码
つまり、or returnステートメントの後には何も続きません。それは可能であり、デフォルトでは破棄されます。
特別なシーン:延期
このセクションは議論のためだけのものですが、この機会にエラーチェックを追加して延期し、何かを実行して新しい処理方法を取得できるかどうかを確認できます。
コアアイデア:返されたエラーを変数に保存して作成するか、延期でトリガーすることができなければ、非常に興味深いでしょう。
以下の例1:
defer f.Close() or return errHdl("", fmt.Errorf("couldn't close file"))
复制代码
変数が明示的に宣言されていない場合、戻り値の型が間違っていてnilに等しくない場合、またはreturnの右側の関数が自動的に呼び出されて処理されます。
以下の例2:
defer err := f.Close() or return errHdl("couldn't close file", err)
复制代码
エラーを受け入れる変数err変数を定義します。これは、またはreturn構文を介してパラメーターを関数errHdlの入力パラメーターに直接渡すことによって使用できます。
結果
新しい構文または戻り構文が追加され、元のエラー処理メカニズムと比較されて、その方法が確認されました。
新着:
func Foo(path string) ([]byte, error) {
errHdlr := func(reason string, err error) ([]byte, error) {
return nil, fmt.Errorf("foo %s %w", reason, err)
}
f, err := os.Open(path) or return errHdlr("couldn't open file", err)
defer f.Close() or return errHdl("", fmt.Errorf("couldn't close file"))
result, err := io.ReadAll(f) or return errHdlr("couldn't read from file " + path, err)
return result, nil
}
复制代码
年:
func Foo(path string) ([]byte, error) {
f, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("foo %s %w", "couldn't open file", err)
}
result, err := io.ReadAll(f)
if err != nil {
return nil, fmt.Errorf("foo %s %w", "couldn't read from file " + path, err)
}
err = f.Close()
if err != nil {
return nil, fmt.Errorf("foo %s %w", "couldn't close the file " + path, err)
}
return result, nil
}
复制代码
これは非常に単純な例ですが、すでにメリットがわかります。コードを読んでいるプログラマーは、左側に集中してエラー処理を無視することもできます。
gofmtでコードをフォーマットした後は、さらに美しくなります。
次の例:
f, err := os.Open(path) or return errHdlr("couldn't open file", err)
defer f.Close() or return errHdl("", fmt.Errorf("couldn't close file"))
result, err := io.ReadAll(f) or return errHdlr("couldn't read from file " + path, err)
复制代码
まったくその通りです。
要約する
この新しい提案では、著者はコメントを求める段階にあります。主にorキーワードなどのさまざまなアイデアを促進し、変数を右側の関数に渡すことができます(左側の関数と式の提案も少し前に共有しました)。
作者の目的は、できるだけ便利にすることであり、過去に誰もが不満を言っていたif err!= nilを書かないことで、より簡潔にすることです。
この提案についてどう思いますか?コメントエリアで交換と議論へようこそ。
記事は継続的に更新されており、WeChatで[Brain Fried Fish]を検索して読むことができます。この記事は、 GitHubgithub.com/eddycjy/bloに 含まれています。ルート。スターへようこそ。更新を促します。
ゴーブックシリーズ
- Go言語シリーズの概要:Goプロジェクトの実際の戦闘の予備調査
- Goプログラミングジャーニー:Goプロジェクトの詳細
- Go言語デザイン哲学:GoWhyとデザイン思考を理解する
- Go Language Advanced Tour:Goソースコードをさらに深く掘り下げます