error는 Error이라는 하나의 메서드만 선언되 있다. 이 메서드는 에러 정보를 담고 있는 string을 반환한다. 따라서 Error()메서드만 구현하는 것 만으로 모든 코드에서의 사용이 가능하다.
Go는 표준 라이브러리 형식으로 errorString 구조체 타입을 제공한다. 이 구조체는 errors 패키지에 선언돼 있다.
예제에서 애플리케이션 에러를 처리하기 위해서 UserId와 OriginalError 필드를 포함하는 UnauthorizedError 구조체를 만들었다. fmt.Errorf 메서드를 이용해서 시스템 에러 정보를 포함한 error를 반환한다.
main 함수내에서는 error를 처리하는 것과 동일한 방식으로 에러를 처리 할 수 있다. error structure에 추가된 컨텍스트는 디버깅 목적으로만 사용한다. 디버깅 목적으로 사용하고 싶다면 type assertion 처리를 해야 한다. 위 코드를 디버깅 목적으로 수정했다.
먼저 상태정보와 메서드 정보를 담기 위한 필드를 포함한 HttpError 구조체를 만들었다. 그리고 Error() 메서드를 구현해서 오류 인터페이스를 구현한다. 이 에러메시지는 상태값과 메서드같은 상세정보를 리턴한다.
GetUserEmail은 HTTP 유저 아이디에 대한 이메일 정보를 리턴하는 모의 함수다. userId가 1일때는 StatusForbidden, 2일때는 StatusNotFound ... 를 리턴하게했다.
main 함수에서 GetUserEmail 함수를 호출하면 유저의 email과 err를 반환한다. err은 error의 인터페이스다. 만약 에러가 StatusForbidden 이면, 세션정리를 하는 작업을 수행하도록 했다.
type switch를 이용해서 다른 방식으로 구현 할 수도 있다. 아래 코드를 보자.
네트워크 에러와 파일 에러메시지를 위해서 NetworkError와 FileSaveFailedError 구조체를 마들고 error 인터페이스를 위한 Error() 메서드를 만들었다. saveFileToRemote 함수는 에러에 맞는 structure를 리턴한다.
main 함수에서 saveFileToRemote 함수를 호출하면 error를 리턴한다. 이제 error의 타입을 확인해서 switch로 분기처리 하면 된다.
임베디드(embeded) 인터페이스를 이용하면 여러 인터페이스를 병합한 인터페이스를 만들 수 있다. 이 원리를 이용하면 오류 인터페이스와 추가적인 메서드를 포함한 인터페이스를 만들 수 있다. 이 인터페이스는 에러 메서드와 (주로 에러 분석을 위한)여러 가지 메서드들을 포함 할 수 있다.
약간 혼동될 수 있는데(인터페이스 들어가면 혼동되기 마련이다.) 간단하다. isLoggineIn 메서드와 getSessionId 메서드를 포함하는 UserSessionState 인터페이스가 있다. 그리고 error 인터페이스도 가지고 있다. 따라서 UserSessionState는 error를 표현하기 위한 타입으로 사용 할 수 있다.
UnauthorizedError 구조체는 getSessionId와 isLoggedIn 메서드 Error 메서드를 모두 구현하고 있기 때문에, error와 UserSessionState 인터페이스를 모두 구현하고 있다. 아래 그림은 이 구조를 묘사하고 있다.
위의 예제에서는 동일한 에러를 두번 기록한다. 함수는 중첩해서 호출할 수 있기 때문에 같은 에러가 여러번 로깅 될 수 있다. 중복된 정보는 좋지 않다. 따라서 로그를 기록할 적당한 위치를 설정하는 것도 중요하다. 일반적으로 정렬 함수와 같은 유틸리티 함수는 에러를 처리하지 않는다. 에러에 대한 처리는 호출하는 쪽의 책임이다.
Contents
1. Go 언어에서의 error
2. Error 인터페이스와 errorString 구조체
3. Error 값만들기
4. Error 값 비교하기
5. Error wrapping
6. 사용자 정의 error interface
7. 에러 핸들링 팁
7.1. 에러 무시
7.2. 에러만 반환하는 건 좋은 생각은 아니다.
7.3. 한번에 여러 개의 에러를 다루지 말자
1. Go 언어에서의 error
2. Error 인터페이스와 errorString 구조체
3. Error 값만들기
4. Error 값 비교하기
5. Error wrapping
6. 사용자 정의 error interface
7. 에러 핸들링 팁
7.1. 에러 무시
7.2. 에러만 반환하는 건 좋은 생각은 아니다.
7.3. 한번에 여러 개의 에러를 다루지 말자
Recent Posts
Archive Posts
Tags