모범 사례 — 오류 처리

이 기사는 Go in production에서 몇 년 동안 배운 일련의 교훈 중 첫 번째 기사입니다. 우리는 Saltside Technologies (psst, Bangalore에서 Saltside를 위해 여러 직책을 맡고 있음)에서 생산에 많은 Go 서비스를 운영하고 있으며 Go가 필수 요소 인 자체 비즈니스도 운영하고 있습니다.

우리는 크고 작은 다양한 주제를 다룰 것입니다.

이 시리즈에서 다루고 자하는 첫 번째 주제는 오류 처리입니다. 종종 새로운 Go 개발자에게 혼란과 성가심을 유발합니다.

일부 배경 — 오류 인터페이스

우리는 같은 페이지에 있습니다. Go에서 오류를 알 수 있듯이 단순히 오류 인터페이스를 구현하는 것입니다. 인터페이스 정의는 다음과 같습니다.

오류 인터페이스 유형 {
    Error () 문자열
}

따라서 Error () 문자열 메서드를 구현하는 모든 것을 오류로 사용할 수 있습니다.

오류 확인

오류 구조 및 유형 검사 사용

Go를 쓰기 시작했을 때 종종 오류 메시지의 문자열 비교를 통해 오류 유형이 무엇인지 확인했습니다 (예, 생각하기가 창피하지만 때로는 되돌아보아야 할 때가 있습니다).

더 나은 방법은 오류 유형을 사용하는 것입니다. 따라서 오류 인터페이스를 구현하는 구조체를 만든 다음 switch 문에서 형식 비교를 수행 할 수 있습니다.

다음은 오류 구현 예입니다.

ErrZeroDivision struct 유형 {
    메시지 문자열
}
func NewErrZeroDivision (메시지 문자열) * ErrZeroDivision {
    & ErrZeroDivision {리턴
        메시지 : 메시지,
    }
}
func (e * ErrZeroDivision) Error () 문자열 {
    전자 메일 회신
}

이제이 오류를 이렇게 사용할 수 있습니다.

func main () {
    결과, 오류 : = 나누기 (1.0, 0.0)
    err! = nil {
        스위치 오류. (유형) {
        사례 * ErrZeroDivision :
            fmt.Println (err.Error ())
        기본:
            fmt.Println ( "h * 무슨 일이 있었나요?")
        }
    }
    fmt. 프린트 (결과)
}
func 나누기 (a, b float64) (float64, 오류) {
    b == 0.0 {
        0.0, NewErrZeroDivision ( "0으로 나눌 수 없음")을 반환
    }
    반환 a / b, nil
}

전체 예를 보려면 Go Play 링크가 있습니다. 스위치 err. (type) 패턴을 주목하십시오. 이것은 문자열 비교 나 유사한 것과 같은 다른 것보다는 다른 에러 유형을 확인할 수있게합니다.

오류 패키지 및 직접 비교 사용

위의 방법은 오류 패키지를 사용하여 처리 할 수도 있습니다. 이 방법은 빠른 오류 표현이 필요한 패키지 내의 오류 검사에 권장됩니다.

var errNotFound = errors.New ( "항목을 찾을 수 없습니다")
func main () {
    err : = getItem (123) // errNotFound를 던집니다
    err! = nil {
        스위치 오류 {
        사례 errNotFound :
            log.Println ( "요청한 항목을 찾을 수 없습니다")
        기본:
            log.Println ( "알 수없는 오류가 발생했습니다")
        }
    }
}

이 방법은 더 복잡한 오류 객체가 필요할 때 덜 효과적입니다. 이 경우 오류 인터페이스를 구현하는 고유 한 유형을 작성해야합니다.

즉각적인 오류 처리

때로는 아래와 같은 코드가 나오지만 (보통 더 보풀이 있습니다.) :

func example1 () 오류 {
    err : = call1 ()
    오류를 반환
}

여기서 요점은 오류가 즉시 처리되지 않는다는 것입니다. 누군가가 err : = call1 ()과 return err 사이에 코드를 삽입 할 수 있기 때문에 깨지기 쉬운 접근 방식입니다. 이는 의도를 깨뜨릴 수 있기 때문에 첫 번째 오류를 숨길 수 있습니다. 두 가지 대체 방법 :

// 반환과 오류를 접습니다.
func example2 () 오류 {
    리턴 콜 1 ()
}
// 호출 직후에 명시적인 오류 처리를 수행합니다.
func example3 () 오류 {
    err : = call1 ()
    err! = nil {
        오류를 반환
    }
    nil을 반환
}

위의 두 가지 접근 방식은 모두 괜찮습니다. 그들은 같은 것을 성취합니다. 누군가 call1 () 뒤에 무언가를 추가 해야하는 경우 오류 처리를 처리해야합니다.

오늘은 그게 다야

Go Best Practices에 대한 다음 기사를 계속 지켜봐 주시기 바랍니다. 강해 :).

func main () {
    err : = readArticle ( "고용 사례-오류 처리")
    err! = nil {
        ping ( "@ sebdah")
    }
}