프로그래밍Go 개발자

Go에서 오류 처리의 특징은 무엇이며, 오류를 올바르게 생성하고 처리하는 방법과 사용자 정의 오류 유형을 구현하는 방법은 무엇입니까?

Hintsage AI 어시스턴트로 면접 통과

답변

Go는 처음부터 예외 대신 명시적인 오류 반환을 중심으로 설계되었습니다. 이는 예측 가능한 코드를 개발하고 Java나 C++와 같은 다른 언어의 try/catch 구조에 내재된 숨겨진 함정을 피할 수 있게 해줍니다. Go에서 오류는 Error() 메서드를 구현하는 인터페이스로, 간단하거나 복합적인/래핑된 오류를 컨텍스트와 함께 생성할 수 있습니다.

오류 처리를 잘못하면(예: _를 통해 무시하거나 디버깅을 위한 추가 정보 없이 래핑하지 않음) 문제가 발생하거나 인터페이스 오류에 맞지 않는 "마법의" 오류를 생성하게 됩니다. 또한 공개 함수에서 오류를 반환하고 각 호출 시 이를 확인하는 것도 중요합니다.

해결책은 표준 접근 방식을 사용하는 것입니다:

  • 항상 함수의 마지막 값으로 오류를 반환하십시오.
  • errors.New, fmt.Errorf를 사용하여 오류를 생성하십시오.
  • 사용자 정의 오류의 경우 Error()를 구현하는 자체 유형을 생성하십시오.
  • 복잡한 사례에는 오류 래퍼(errors.Wrap)를 사용하여 컨텍스트를 잃지 않도록 하십시오.

코드 예:

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) }

주요 특징:

  • 오류는 항상 명시적으로 반환되며, 일반적으로 함수의 마지막 인수로 반환됩니다.
  • 복잡한 오류의 경우 interface error를 구현하는 자체 유형(struct)을 정의할 수 있습니다.
  • 오류를 래핑하고 스택 추적을 저장하려면 "errors" 패키지를 사용할 수 있습니다(Go 1.13+는 errors.Is 및 errors.As를 지원하여 오류 체인 작업을 수행할 수 있습니다).

헷갈리기 쉬운 질문.

오류를 처리할 때 ==를 사용하여 비교할 수 있습니까, 아니면 특별한 메서드를 사용해야 합니까?

오류 래퍼와 비교할 때는 항상 errors.Is()를 사용하는 것이 좋습니다. 그렇지 않으면 오류가 래핑된 경우 == 비교가 작동하지 않을 수 있습니다.

if errors.Is(err, os.ErrNotExist) { // 파일 없음 처리 }

사용자 정의 오류에 대해 구조체 유형을 구현해야 하나요, 아니면 errors.New("...")를 사용하는 것으로 충분한가요?

오류 메시지만 필요하면 errors.New()로 충분합니다. 컨텍스트(예: 리소스 이름)를 유지하는 것이 중요하다면 Error() 메서드가 있는 struct를 정의하는 것이 좋습니다.

함수가 성공적으로 실행된 경우 오류를 올바르게 어떻게 반환합니까?

성공 시 항상 nil 오류를 반환해야 합니다.

return result, nil

일반적인 오류 및 안티패턴

  • 오류 반환을 무시함(=_ 또는 처리 생략)
  • 중첩된 오류가 있음에도 불구하고 ==로만 오류 비교하기
  • 오류 대신 하드코딩된 문자열 사용하기
  • 오류에 추가 컨텍스트 없음

실제 예시

부정적인 사례

개발자가 설명 없이 오류를 반환하는 함수를 작성합니다(그냥 errors.New("fail")). 로그를 분석할 때 원인을 파악할 수 없습니다.

장점:

  • 구현 속도

단점:

  • 비정보적인 오류
  • 디버깅의 어려움

긍정적인 사례

개발자가 사용자 정의 오류 유형 NotFoundError를 정의하고 이를 자세히 설명하여 반환합니다.

장점:

  • 로그 필터링의 편리함
  • 오류 검색 및 처리의 용이성

단점:

  • 추가 구조 설명 필요