最終更新日: 2026-07-25
TOP(About this memo)) > 一覧(Go) > エラーハンドリング
if strings.Contains(err.Error(), "cannot unmarshal") {
logger.Warn(c.RequestID, "Invalid field format:%s", err)
return ErrRequestFieldFormat
}
func f1() {
defer print("f1 defer\n") // deferは呼ばれる。
panic("f1 panic!!!!")
print("not execute!!!") // 実行されない
}
func f2() {
defer print("f2 defer\n") //呼び出し元のdeferも呼ばれる。
f1()
}
func main() {
f2()
print("not execute!!!") // 実行されない
}
// f1 defer
// f2 defer
// panic: f1 panic!!!!
func main() {
recover()
panic("パニックが回収されませんでした")
}
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("パニックが回収されました")
}
}()
panic("パニックが回収されませんでした")
}
func main() {
s := f()
fmt.Printf("%#v\n", s)// <nil>になる。
}
func f() error {
var r interface{}
defer func() {
r = recover()
if r != nil {
println(r.(string))
}
}()
if true {// 分岐を挟んでいるのは、go vet による nerver reached codeの回避のため。
panic("fff")
}
return errors.New("aaa") // ここは実行されない。
}
// /usr/local/go/src/builtin/builtin.go
type error interface {
Error() string
}
// /usr/local/go/src/errors/errors.go
func New(text string) error {
return &errorString{text}
}
type errorString struct {
s string
}
type wrapError struct {
msg string
err error
}
func (e *wrapError) Unwrap() error {
return e.err
}
func main() {
fmt.Println(fmt.Errorf("wrapping: %w", testErr()))
}
func testErr() error {
return errors.New("test error")
}
type ErrRequestJsonSomethingInvalid struct {
Json string
Err error
}
func (e *ErrRequestJsonSomethingInvalid) Error() string {
return fmt.Sprintf("json is something invalid: %s", string(e.Json))
}
func (e *ErrRequestJsonSomethingInvalid) Unwrap() error {
return e.Err
}
import (
"encoding/json"
"errors"
"strings"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)
func Ptr[T any](a T) *T {
return &a
}
func TestError(t *testing.T) {
t.Run("assert_error", func(t *testing.T) {
//errors.IsはDeep equalではない。したがってこれはfalseになる
assert.Equal(t, errors.Is(errors.New(""), errors.New("")), false)
a := errors.New("")
assert.Equal(t, errors.Is(a, a), true) // これはtrue
// AssertFalse(t, errors.As(errors.New(""), Ptr(errors.New("")))) これだとanalyzerのerrorになる。(第二引数がerror型は駄目らしい)
// Unmarshalで発生するエラーの判定の例
assert.Equal(t, errors.As(json.Unmarshal([]byte("{"), &struct{}{}), Ptr(&json.SyntaxError{})), true)// json.SyntaxErrorはポインタレシーバーのため、&json.SyntaxError{}を渡す必要があり、errors.Asの第二引数targetはerror型へのポインタである必要があるため、Ptr(&json.SyntaxError{})を渡す。
assert.Equal(t, errors.As(json.Unmarshal([]byte(`{"id":"a"}`), &struct {
Id int `json:"id"`
}{}), Ptr(&json.UnmarshalTypeError{})), true)
assert.Equal(t, errors.As(json.Unmarshal([]byte(`{"id":"a"}`), (*int)(nil)), Ptr(&json.InvalidUnmarshalError{})), true)
// uuidの実装はエラーの定義がないため、errros.Isで比較できないため文字列で比較する必要がある。
strings.Contains(json.Unmarshal([]byte(`{"id":"a"}`), &struct {
Id uuid.UUID `json:"id"`
}{}).Error(), "invalid UUID length")
assert.Equal(t, json.Unmarshal([]byte(`{"id":"g0000000-0000-0000-0000-000000000000"}`), &struct {
Id uuid.UUID `json:"id"`
}{}).Error(), "invalid UUID format")
})
}