超簡単な要約: エラーが発生した場合は、プログラムを終了することをお勧めします。 Gobail を使用すると、生活が楽になります。
Go コードでエラーが発生すると、通常は次のようなメッセージが表示されます。
err := myFunc() if err != nil { return fmt.Errorf("doing my thing: %w", err) }
この例ではいくつかのことに気づくでしょう:
それでは、次に何が起こるのでしょうか?まあ、すべてはまた起こるのです。エラー値を確認し、説明して返します。そして、すべてが再び始まります。
なぜこれを行うのでしょうか?なぜこれほどの努力をするのでしょうか?
まあ、それはすべてあなたが作成しているソフトウェア次第です。エラーが発生した場合は、決定を下す必要があります。そのエラーはどうなりますか?
リクエストに応答する HTTP API を作成している場合、最終的にはある種の HTTP ハンドラーに到達し、そのエラーを何らかの応答に変換することになります。おそらく、丁寧なリマインダー形式の小さな 400 です。適切にリクエストするか、場合によっては 500 とアプリケーションの健全性に関する懸念メッセージをリクエストします。あるいは、何らかの CLI ツールを作成している場合は、エラーが最終的にメイン関数にずっと返されると判断することもできます。どのような種類のプログラムでも、もう十分だと判断するかもしれません。他に何もできないのでプログラムは終了するべきです。
この最後のオプションを見てみましょう。プログラムを終了するのが適切なのはどのような場合ですか?考えられる理由は次のとおりです。
a.他にできることはありません。エラーがひどいため、今すぐすべてを停止する必要があります
b.プログラムを終了しても影響はありません (クリーンアップは必要なく、応答するステータスもありません)
c.早めに停止することが望ましいですが、プロセスを正常に再起動するモニターがある可能性があります
理由が何であれ、きれいに終了する方法を考える必要があります。まず最初に試してみることは次のとおりです:
err := myFunc() if err != nil { fmt.Printf("doing my thing: %v", err) os.Exit(1) }
これは元のエラー処理コードとかなり似ていますが、いくつかの重要な違いがあります。 1 つ目は、ある意味明らかです。そこには、素晴らしい stop-right-g*****n-now ステートメントが鳴っています。あなたのプログラムは続行されません。 2 番目の点はおそらくより重要です。このサンプルを呼び出しているコードでは、エラーの処理について心配する必要はありません。テストする必要がある追加のコード パスはありません。確認する必要があるものは何も返されないため、呼び出し元のコードにはテストする if ブロックがないことが信頼できます。
だから、終了コードが正しく機能することを信じるべきだと私が提案したとき、私はおそらく少し熱心だったのでしょう。新しいプログラムが停止した理由が正しいかどうかを確認する必要があります。
これは簡単なはずです。考慮すべき点がいくつかあります。最も簡単なケースでは、プログラムを実行してエラー状態を引き起こすだけです。たとえば、存在しないファイルを開くために CLI ツールを取得します。いくつかの単純なケースでは、これを手動で行うことができます。テストの数が増えると、おそらくそれを支援する何らかの自動化が必要になるでしょう。
簡単な補足 - これはおそらく別のブログ投稿の主題ですが、CLI ツールをテストする私の現在のお気に入りの方法は、godog を使用してテストを作成します。少し複雑かもしれませんが、非常に強力であることがわかりました。ここでは、私がlayliとwait-forを使ってそれにどのようにアプローチしたかの良い例をいくつか紹介します。
このアプローチはかなりの成果を上げますが、自信を持って必要なすべてのコード パスを適切に実行する条件を作成するのが難しい場合があります。
それでは、Go 言語の機能のいくつかを使用していきます。実際に os.Exit を呼び出す必要はありません。それに似たものを呼び出すことができます。これを見てください:
err := myFunc() if err != nil { return fmt.Errorf("doing my thing: %w", err) }
それでは、これをテストにどのように利用するのでしょうか?関数が変数 (customExit) に変換されたので、値を他の実行したいものに置き換えることができます。そうですね…
err := myFunc() if err != nil { fmt.Printf("doing my thing: %v", err) os.Exit(1) }
これは、より単体テストに適したアプローチです。使用された終了コードが正しいこと、および実際に exit 関数を呼び出したことを確認できます。
これは表面的には素晴らしいように見えますが、大きな問題が 1 つあります。テストに合格すると、プログラムは続行され、終了すると予想されたときに関数の残りの部分を実行します。テスト設定により、残りの実行が無効になり、パニックが発生するなどテストに問題が発生する場合でも、テストは続行されます。
そうですね、これは少し極端に聞こえます!
説明する必要があるような気がします... 通常、「適切に管理された」企業では、顧客の前に提供できる場合は、コードのすべての行が以前に動作することが証明されていることを確認する必要があります。上記の手法を使用すると、正常であることを証明するための正しいカバレッジ指標を生成できない場合があります。たとえそれが些細な理由であっても。
上記の例はすべて、エラーが発生した場合はそれを確認して何をすべきかを決定する必要がある (復讐して終了する) ことを前提としています。エラーがあることを確認せずに終了できたら素晴らしいと思いませんか?
何ができるか見てみましょう。
err := myFunc() if err != nil { return fmt.Errorf("doing my thing: %w", err) }
上の例を見てください。機能は同じですが、myFunc の実装ははるかに単純になり、条件がなくなりました。 checkExit 関数の実装を独自のテストで確認できます。つまり、myFunc() の新機能をより簡単に検証できます。
新しいライブラリ gobail が作成されました。これにより、エラーが発生した場合でも、独自のコードを複雑にすることなく確実に処理できるようになります。次のようになります:
err := myFunc() if err != nil { fmt.Printf("doing my thing: %v", err) os.Exit(1) }
このライブラリは、カバレッジ メトリックを使用して完全にテストされており、それが証明されています。エラーを飛ばす心配がなく、安心してご利用いただけます。また、次のように 2 つの戻り値を持つ関数も処理します。
type ExitFunc func(code int) var customExit ExitFunc = os.Exit func myFunc() { err := someOtherFunc() if err != nil { fmt.Printf("doing my thing: %v", err) customExit(1) } }
すべての問題の原因となっているエラーが含まれていることにも注意してください。
終了する代わりにパニックを起こし、パニックが呼び出されたときにプログラムからスタック トレースやその他のコンテキスト情報を出力することもできます。詳細については、ドキュメントを参照してください。
gobail を使用してソフトウェアを作成すると、外部ライブラリと通信するときに主に gobail を使用する必要があることに気づくでしょう。これには、すべてのエラーケースを処理するために通常記述する必要がある追加コードがあり、Return または Return2 への呼び出しでラップすることができ、必要に応じて終了すると想定されます。
エラーを詳細に処理するのではなく、プログラムを終了することが望ましい場合があります。 Gobail ライブラリは作成および検証されているため、これを証明する詳細について心配する必要はありません。
改善できる点を見つけた場合、または単に提案がある場合は、リポジトリで PR または問題を提起してください。開発者は可能な限りそれに取り組みます。
以上が勝つためには早めにやめましょう!の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。