Go는 처음부터 예외 대신 명시적인 오류 반환을 중심으로 설계되었습니다. 이는 예측 가능한 코드를 개발하고 Java나 C++와 같은 다른 언어의 try/catch 구조에 내재된 숨겨진 함정을 피할 수 있게 해줍니다. Go에서 오류는 Error() 메서드를 구현하는 인터페이스로, 간단하거나 복합적인/래핑된 오류를 컨텍스트와 함께 생성할 수 있습니다.
오류 처리를 잘못하면(예: _를 통해 무시하거나 디버깅을 위한 추가 정보 없이 래핑하지 않음) 문제가 발생하거나 인터페이스 오류에 맞지 않는 "마법의" 오류를 생성하게 됩니다. 또한 공개 함수에서 오류를 반환하고 각 호출 시 이를 확인하는 것도 중요합니다.
해결책은 표준 접근 방식을 사용하는 것입니다:
코드 예:
import ( "errors" "fmt" ) type NotFoundError struct { Resource string } func (e *NotFoundError) Error() string { return fmt.Sprintf("%s not found", e.Resource) } func GetUser(id int) (string, error) { if id != 1 { return "", &NotFoundError{"User"} } return "Steve", nil } func main() { user, err := GetUser(2) if err != nil { if nfe, ok := err.(*NotFoundError); ok { fmt.Println(nfe.Resource, "문제") } else { fmt.Println("오류:", err) } } fmt.Println("사용자:", user) }
주요 특징:
오류를 처리할 때 ==를 사용하여 비교할 수 있습니까, 아니면 특별한 메서드를 사용해야 합니까?
오류 래퍼와 비교할 때는 항상 errors.Is()를 사용하는 것이 좋습니다. 그렇지 않으면 오류가 래핑된 경우 == 비교가 작동하지 않을 수 있습니다.
if errors.Is(err, os.ErrNotExist) { // 파일 없음 처리 }
사용자 정의 오류에 대해 구조체 유형을 구현해야 하나요, 아니면 errors.New("...")를 사용하는 것으로 충분한가요?
오류 메시지만 필요하면 errors.New()로 충분합니다. 컨텍스트(예: 리소스 이름)를 유지하는 것이 중요하다면 Error() 메서드가 있는 struct를 정의하는 것이 좋습니다.
함수가 성공적으로 실행된 경우 오류를 올바르게 어떻게 반환합니까?
성공 시 항상 nil 오류를 반환해야 합니다.
return result, nil
부정적인 사례
개발자가 설명 없이 오류를 반환하는 함수를 작성합니다(그냥 errors.New("fail")). 로그를 분석할 때 원인을 파악할 수 없습니다.
장점:
단점:
긍정적인 사례
개발자가 사용자 정의 오류 유형 NotFoundError를 정의하고 이를 자세히 설명하여 반환합니다.
장점:
단점: