Goのエラーチェーンでエラーが起こった流れを把握する

Go

Goにはスタックトレース機構がないので、どういう流れで処理が行われたのかが把握できない。

そのため、一番初めの呼び出し元にエラーをラップして戻す方法で、エラーの流れを把握する。

package main

import (
	"errors"
	"fmt"
)

type queryResult struct{}

func queryDatabase() (result *queryResult, err error) {
	// なにかしらの処理をしたと仮定
    // 一番最初のエラー
	return result, errors.New("database is down")
}

func fetchData() (result *queryResult, err error) {
	res, err := queryDatabase()
	if err != nil {
        // エラーをラップして返す
		return &queryResult{}, fmt.Errorf("fetchData failed: %w", err)
	}
	return res, nil
}

func process() (result *queryResult, err error) {
	res, err := fetchData()
	if err != nil {
        // エラーをラップして返す
		return &queryResult{}, fmt.Errorf("process failed: %w", err)
	}
	return res, nil
}

func main() {
    // 今までの処理のエラーがまとめて返ってくる
	res, err := process()
	if err != nil {
		fmt.Println(err)
		// 出力: process failed: fetchData failed: database is down
	}

	fmt.Println(res)
}

このようにすると、どういう流れで処理が行われ、どのようなエラーが起こったか把握できる。