MENU

【Go】エラーが発生した箇所のファイル名と行番号が欲しい

Goのエラーはシンプルで、基本的にエラーメッセージのみを返します。

シンプルゆえに、僕からするとメッセージだけ見ても「このエラーはどこで発生しているんだ?」と、まず発生箇所を探すことから始めないといけません。

エラー原因をスムーズに取り除きたいですが、結構モタモタしてしまいます。

なので今回はエラー自体にファイル名と行番号を組み込み、素早く発生箇所にたどり着けるようにしたいと思います。

目次

エラーの発生箇所を取得しよう

これは runtime パッケージを使うだけでOKです。

runtime.Caller を使うことで、発生箇所のファイル名と行番号を取得できます。関数名なんかも取得できますが今回はスルーします。

import (
	"runtime"
)

// getCallerInfo は呼び出し元のファイル名と行番号を返します。
func getCallerInfo(dept int) (filename string, line int) {
	// 関数名も取得したい場合は、Caller(dept) の1つ目の返り値も使います。
	_, filename, line, ok := runtime.Caller(dept)
	if !ok {
		return "failed to get file and line information", 0
	}
	return filename, line
}

これだけでエラーが発生した箇所の情報を取得できます。

あとはこれを組み込んだカスタムエラーを実装するだけです。

カスタムエラー実装

シンプルなエラーを実装します。

package main

import (
	"fmt"
	"runtime"
)

// MyError は、エラーメッセージ、発生したファイル名、および行番号を保持します。
type MyError struct {
	msg  string
	file string
	line int
}

func (e MyError) Error() string {
	return fmt.Sprintf("file=%s, line=%d, msg=%s", e.file, e.line, e.msg)
}

// New は新しい MyError を作成します。
// エラーメッセージと、発生箇所のファイル名と行番号を取得します。
func New(msg string) *MyError {
	filename, line := getCallerInfo(2)
	return &MyError{
		msg:  msg,
		file: filename,
		line: line,
	}
}

// getCallerInfo は呼び出し元のファイル名と行番号を返します。
func getCallerInfo(dept int) (filename string, line int) {
	// 関数名も取得したい場合は、Caller(dept) の1つ目の返り値も使います。
	_, filename, line, ok := runtime.Caller(dept)
	if !ok {
		return "failed to get file and line information", 0
	}
	return filename, line
}

// 確認用。
func doSomething() error {
	err := New("failed to do something")
	return err
}

func main() {
	err := doSomething()

	fmt.Println(err) // file=xxx/main.go, line=40, msg=failed to do something
}

終わり

以上です。

これで発生箇所がすぐにわかるので、対処しやすくなりました!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

コメントは日本語で入力してください。(スパム対策)

CAPTCHA

目次