Go 言語でエラーを返却し、受け取った側で適切に処理する
はじめに
エラーハンドリングは、コードの安定性・堅牢性には必要不可欠です。
今回は、 前回作成した greetings
モジュール に少しだけコードを追加しながら、以下の内容について学んで行きます。
- モジュールからエラーを返却する方法
- モジュールから返却されたエラーを呼び出し元でハンドリングする方法
当エントリは以下のエントリの続きとなっています。事前に一読しておくことをおすすめします。
コーディング開始
早速コーディングを始めていきます。
1. greetings/greetings.go
を開き、コードを追記
「挨拶をする相手の名前がわからない場合には、挨拶をせずにエラーとする」、 そんな仕様を追加してみます。
name
パラメータが空だった場合には、呼び出し元にエラーを返却します。 以下のコードを greetings.go
に記述します。
package greetings
import (
"errors"
"fmt"
)
func Hello(name string) (string, error) {
if name == "" {
return "", errors.New("empty name")
}
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message, nil
}
もともとのコード から変更した箇所は以下のようになります。( git diff
実行結果を添付 )
@@ -1,9 +1,16 @@
package greetings
-import "fmt"
+import (
+ "errors"
+ "fmt"
+)
+
+func Hello(name string) (string, error) {
+ if name == "" {
+ return "", errors.New("empty name")
+ }
-func Hello(name string) string {
message := fmt.Sprintf("Hi, %v. Welcome!", name)
- return message
+ return message, nil
}
コード解説
かんたんに解説します。
- 関数は 2 つの値を返却するように変更されています。
- 1 つは string 型の値、 1 つは error 型の値。
- 呼び出し元では 2 つ目に返却された値をチェックすることで、エラーが発生したかがわかります ( Go の関数は複数の値を返却することができるんですね ) 。
- Go の
errors
という標準ライブラリをインポートし、errors.New
関数 ( 後述 ) を利用できるようにします。 if
構文を使って、name
パラメータが妥当か(空ではないか?)をチェックしています。- 空の場合
- エラーを返却します。
- エラーを返却する場合は、 error 型の値を生成するために
errors.New
関数を利用します。任意のメッセージを格納することができます。 - 空でない場合
- エラーを返却しません。
- エラーを返却しない場合は、 2 つ目の戻り値に
nil
を設定します。
Hello
関数の呼び出し元は 2 つ目の戻り値を確認し、 nil
であれば正常終了したと判断できます。
2. hello/hello.go
を開き、 Hello
関数からの戻り値をハンドリングするコードを追加
以下のコードを貼り付けます。
package main
import (
"fmt"
"log"
"genzouw/greetings"
)
func main() {
log.SetPrefix("greetings: ")
log.SetFlags(0)
message, err := greetings.Hello("")
if err != nil {
log.Fatal(err)
}
fmt.Println(message)
}
もともとのコード から変更した箇所は以下のようになります。( git diff
実行結果を添付 )
$ git diff
diff --git hello.go hello.go
index 747ec74..22adb60 100644
--- hello.go
+++ hello.go
@@ -2,11 +2,20 @@ package main
import (
"fmt"
+ "log"
+
"genzouw/greetings"
)
func main() {
- message := greetings.Hello("genzouw")
+ log.SetPrefix("greetings: ")
+ log.SetFlags(0)
+
+ message, err := greetings.Hello("")
+
+ if err != nil {
+ log.Fatal(err)
+ }
fmt.Println(message)
}
コード解説
かんたんに解説します。
log
パッケージを import しています。- すべてのログのプレフィックスとして
greetings:
という文字列を出力する。 - すべてのログのプレフィックスとして タイムスタンプ や ソースコード名 を出力しない。 (
log.SetFlags(0)
)
- すべてのログのプレフィックスとして
Hello
関数の戻り値 2 つを受け取ります。Hello
関数の引数を変更し、genzouw
という名前 から 空文字 をセットするようにしています。err
変数が nil ではない場合、処理を中断します。- 標準ライブラリ
log
のFatal
関数を呼び出すことで、エラーメッセージを出力しています。log.Fatal
実行後はプログラムがエラーステータスで終了します。
アプリケーション実行
hello
モジュールの配置されているディレクトリで、コードを実行してみます。
$ go run .
greetings: empty name
exit status 1
想定通り、異常終了してくれました。
greetings.Hello("")
の部分を greetings.Hello("genzouw")
のように空文字列ではないものに変更すれば、正常に動作します。
$ go run .
Hi, genzouw. Welcome!
まとめ
Go 言語では、関数の呼び出し元にエラーを通知する方法として、C++/Java/C#といった他の言語のように 「例外を投げる方法」 ではなく、 「戻り値として返却する方法」 を取ります。
ひとこと
次回は 「挨拶」プログラムの実行結果を実行のたびにランダムに変更 してみます。
ディスカッション
コメント一覧
まだ、コメントがありません