GO) 에러 핸들링

soony·2023년 9월 25일

Go

목록 보기
2/2
post-thumbnail

Error 선언

2가지 방법으로 Error를 선언할 수 있다.

따라서 두 가지 방법을 나누는 기준에는 sentinel error 에러 인지에 따라 나눈다.

sentinel error는 더 이상 처리할 수 없는 에러를 말한다.

  • var ErrNotFound = errors.New("error not found")
    -> sentinel error를 다룰 때 사용한다.
  • err := fmt.errorf("%w",err)
    -> sentinel error가 아닐 때 사용한다.

주의 사항

  • Err~ 형태의 cammel case로 변수명을 선언한다. 또는
    ~Error 형태의 cammel case로 변수명을 선언한다.

  • 에러 내용에는 대문자를 사용하지 않는다.

  • 에러 내용에는 마침표를 사용하지 않는다.

  • 에러 내용에는 failed 와 같은 단어를 사용하지 않는다.

Error는 최소한으로

call stack이 깊어 질수록 err를 반환하는 함수가 늘어가기 마련이다.

불리는 함수 마다 에러를 로깅 한다면 성능상 문제와

정확한 에러 문구를 찾기에도 힘들 것이다.

가장 상위 함수에서 한번만 로깅하자.

callee 함수의 경우에는 cool 하게 caller 에게 아무것도 하지 않고 넘겨 주자.

u, err := getUser(id)
if err != nil {
  return fmt.Errorf("get user %q: %w", id, err)
}

Error wrapping

  • %w 는 항상 마지막에!
// Good:
err1 := fmt.Errorf("err1")
err2 := fmt.Errorf("err2: %w", err1)
err3 := fmt.Errorf("err3: %w", err2)
fmt.Println(err3) // err3: err2: err1
// err3 is a newest-to-oldest error chain, that prints newest-to-oldest.
// Bad:
err1 := fmt.Errorf("err1")
err2 := fmt.Errorf("%w: err2", err1)
err3 := fmt.Errorf("%w: err3", err2)
fmt.Println(err3) // err1: err2: err3
// err3 is a newest-to-oldest error chain, that prints oldest-to-newest.
u, err := getUser(id)
if err != nil {
  return fmt.Errorf("get user %q: %w", id, ErrNotFound)
}

이미 선언된 에러코드(ErrNotFound)에 함수의 context를 담고 싶을 때에는
위의 코드 처럼 사용하면 된다.

example)

var (
	ErrConnectionFailed   = errors.New("connection error")
	ErrConnectionTimedOut = errors.New("connection timed out")
)

func DoStuff() error {
	return fmt.Errorf("%v : %w", "do stuff", ErrConnectionFailed)
}

func main() {
	err := DoStuff()
	fmt.Printf("v",err)
    log.Errorf("%v",err)
}

결과:
do stuff : connection error
2023/09/25 09:16:51 do stuff : connection error

Error.Is() / Error.As()

추후 업데이트

출처:

profile
하루의성과

0개의 댓글