Error Handling
defer: Closeのエラーは明示的に返さなければ失われる
deferでCloseを呼ぶだけでは、その失敗を関数の返り値へ反映できません。
Sourceclose_error.go
Go 1.22
package deferflow
import "errors"
var ErrClose = errors.New("close failed")
type failingCloser struct{}
func (failingCloser) Close() error {
return ErrClose
}
func IgnoreCloseError() error {
closer := failingCloser{}
defer closer.Close()
return nil
}
func ReturnCloseError() (err error) {
closer := failingCloser{}
defer func() {
if closeErr := closer.Close(); err == nil {
err = closeErr
}
}()
return nil
}Testclose_error_test.go
Go 1.22
package deferflow
import (
"errors"
"testing"
)
func TestDeferしたCloseのエラーは明示的に返さなければ失われる(t *testing.T) {
if err := IgnoreCloseError(); err != nil {
t.Fatalf("IgnoreCloseError() = %v, want nil", err)
}
if err := ReturnCloseError(); !errors.Is(err, ErrClose) {
t.Fatalf("ReturnCloseError() = %v, want ErrClose", err)
}
}01Assertion
このテストで確認できること
- defer closer.Close()だけではnilが返る
- 名前付き返り値をdeferで更新するとErrCloseを返せる
書き込み系のCloseやflushでは、最後の失敗が重要になる場合があります。主処理のエラーを優先する規約も含め、closeエラーを返す方針をAPIごとに決めます。
OBSERVED RESULT
defer closer.Close(): nil
return close error: close failed