11
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Go:エラーの出力と処理の基本

Last updated at Posted at 2024-09-19

はじめに

こんにちは!株式会社HRBrainの25卒インターン生のizutakuです!
Goで個人開発を行っていた際、エラーハンドリングに一貫性が無いことに気づいたため、改めてエラーハンドリングの基礎を学びました。
この記事では主に以下のパッケージを使用したエラーハンドリングとカスタムエラーについて紹介しますので、ご興味があれば一読ください!

  • errors
  • fmt
  • log
  • os

errors

シンプルなエラーメッセージを持つオブジェクトを生成する。

main.go
package main

import (
	"errors"
	"fmt"
)

func divide(a, b int) (int, error) {
	err := errors.New("cannot divide by zero") //エラーメッセージを持つオブジェクトを作成

	if b == 0 {
		return 0, err
	}

	result := a / b
	return result, nil
}

func main() {

	result, err := divide(100, 0)
	if err != nil {
		fmt.Println(err) //"cannot divide by zero"と出力される
	} else {
		fmt.Println(result)
	}
}

出力
出力
Cannot divide by zero

fmt

ここではfmt.Errorf()について解説する。
fmt.Sprintf()と同様に書式指定が可能となっている。

main.go
package main

import (
	"fmt"
)

func divide(a, b int) (int, error) {

	if b == 0 {
		err := fmt.Errorf("%vでは割れません。", b)
		return 0, err
	}

	result := a / b
	return result, nil
}

func main() {

	result, err := divide(100, 0)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(result)
	}
}

出力
0では割れません

log

logではエラーメッセージや情報をログとして出力する。(logの出力先指定方法などは追々書いていく。)
logによるエラーハンドリングでは、エラー発生時に以下の動作に分けられる。

  • プログラムを継続させる
  • プログラムを終了させる

プログラムの継続

log.Println()、log.Printf()、log.Sprintf()などが該当する。

main.go
package main

import (
	"fmt"
	"log"
	"os"
)

func main() {

	file, err := os.Open("test.txt")
	if err != nil {
		log.Println(err)
	}

	defer file.Close()

	fmt.Println("エラー出ても実行されるよ")
}

出力
出力
2024/09/17 21:18:52 open test.txt: no such file or directory
エラー出ても実行されるよ

プログラムの終了

log.Fatal()、log.Fatalf()、log.Fatalln()が該当する。

main.go
package main

import (
	"fmt"
	"log"
	"os"
)

func main() {

	file, err := os.Open("test.txt")
	if err != nil {
		log.Fatalln(err)
	}

	defer file.Close()

	fmt.Println("エラーが出たら実行されないよ")
}

出力
出力
2024/09/17 21:19:55 open test.txt: no such file or directory
exit status 1

os

ここではos.Exit(code int)を紹介する。

main.go
package main

import (
	"fmt"
	"os"
)

func main() {

	file, err := os.Open("test.txt")
	if err != nil {
		os.Exit(20)
	}

	defer file.Close()

	fmt.Println("エラー出たら実行されないよ")
}

出力
出力
exit status 20

ステータスコードについて
  • ステータスコードは0~125が推奨されている
  • ステータスコードが0であることは、処理が正常に終了したことを示す
  • ステータスコードが1~125ではエラーを示す
  • ステータスコードの値は任意であり、エラーの種類(不正なフォーマット、認証失敗など)によりステタスコードを統一することでエラー改善をしやすくなる

参照元:https://pkg.go.dev/os#Exit

カスタムエラー

Goではエラーインターフェース(error)を満たすカスタムエラーを定義することで、より詳細なエラー情報を得ることができる。

main.go
package main

import (
	"fmt"
)

type Myerror struct {
	code int
	msg  string
}

func (e *Myerror) Error() string {
	return fmt.Sprintf("エラーコード:%d,エラーメッセージ:%s", e.code, e.msg)

}

func main() {

	err := &Myerror{code: 404, msg: "ページが見つかりません"}
	fmt.Println(err.Error())
}

出力
出力
エラーコード:404,エラーメッセージ:ページが見つかりません

まとめ

今回の解説で取り上げた内容をまとめると以下のようになります。

  • fmt.Errorf()
    fmt.Sprintf()のように書式指定が可能で、エラーメッセージを簡潔に作成できる。エラーを返す際に役立ちます。

  • logパッケージ
    エラーや情報をログとして出力する際に使用します。log.Println()やlog.Printf()などでプログラムを継続させつつエラーを記録でき、log.Fatal()を使うとエラーメッセージを表示しつつプログラムを強制終了させることが可能です。

  • os.Exit()
    指定したステータスコードを返し、プログラムを終了します。正常終了には0を、エラー終了には1~125を使用します。

  • カスタムエラー
    Goではエラーインターフェースを満たすカスタムエラーを定義することで、エラーコードやメッセージを含む独自のエラーを作成できます。これにより、より詳細なエラーメッセージを提供しやすくなります。

以上を踏まえ、Goでは状況に応じた適切なエラーハンドリング方法を選択することが重要です。ログの記録やエラー内容のカスタマイズを活用することで、問題発生時のトラブルシューティングがしやすくなり、プログラムの品質向上につながります。

PR

株式会社HRBrainでは新しいメンバーを募集しています!

11
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?