2014-11-04 4 views
4

이동으로 웹 응용 프로그램을 작성하고 있습니다. 대부분의 오류를 API에서 패닉으로 변환 한 다음 상위 수준의 기능에서 이러한 패닉을 잡아 로그에 기록하고 오류 페이지를 사용자에게 반환하려고합니다. 이 같은웹 응용 프로그램에서 패닉 사용

뭔가 :

func Handler(body func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) { 
    return func(responseWriter http.ResponseWriter, request *http.Request) { 
     defer recoverIfPanic(responseWriter, request) 
     body(responseWriter, request) 
    } 
} 

func recoverIfPanic(responseWriter http.ResponseWriter, request *http.Request) { 
    reason := recover() 
    if reason == nil { 
     return 
    } 
    // log and return http error 
} 

func PanicIf(err error, httpStatus int, description string) { 
    if error != nil { 
     panic(MyPanicStruct{err: err, httpStatus: httpStatus, description: description}) 
    } 
} 

내 실제 코드에서

result, err := SomeApi(...) 
PanicIf(err, http.StatusInternalServerError, "SomeApi") 

99 %의 경우 난 아무것도 할 수 없습니다 합리적인 경우, 예를 들어, SQL 서버가 예기치 않은 오류를 반환하거나 파일 시스템에서 파일이 누락되었습니다.이 상황을 기록하고 오류를 사용자에게 반환하는 것이 좋습니다. 그래서 나는 수동으로 unwrinding 스택을 반환해야하는 이유를 볼 수 없다. 실제로 stacktrace와 컨텍스트를 잃어 버리게되고 오류 이유를 찾기가 더 어려워 질 것이다.

내가 놓친 것이 있습니까?이 방법이 효과가 없을 수 있습니까? 대부분의 Go 관련 기사가 공황/회복을 사용하지 말 것을 권장하는 것 같지만 그 이유는 알 수 없습니다. Java (및 유사한 언어)에서의 오래된 throw-catch 메커니즘과 똑같아 보이며 웹 응용 프로그램에 완벽하게 작동합니다.

답변

10

내가 놓친 것이 있습니까?이 방법이 효과가 없을 수 있습니까?

설명

오늘 (!) "Error handling vs. exceptions redux는"

C++ 예외

가 안전하게 그들은 세 년 전에 그랬던 것처럼 사용하기 어려운 남아에서 Dave Cheney에 의해 11 월 4, 2014. 호출 스택의 일부가 경고없이 폭발 할 수있는 경우 많은 C++ 상점에서 예외를 사용하지 않아도되는 것은 당연한 일입니다. 당신이 충분히 열심히 곁눈질 경우

가 는

이동이 panic라는 기능을 가지고있다, 그리고, 당신이 상상할 수 있습니다

그것은 "Why Go gets exceptions right"(2012 년 이전 Go1.0,하지만 여전히 유효 오늘)을 말한다 그 공포는 던지기와 동일 하, 그러나 너는 틀릴.
당신이 던져 및 예외 당신은 당신의 string 상당에 enum 변환 할 수없는 경우는 예외를 throw 할 수 ++ C의 예를 들어 그것을 발신자의 문제

throw new SomeoneElsesProblem(); 

을하고, 또는 때 문자열에서 날짜를 파싱 할 때 Java에서.
네트워크의 모든 입력을 적대적인 것으로 간주해야하는 인터넷 연결 세계에서 문자열을 매우 예외적으로 구문 분석하지 못했습니다? 당연히 아니지.

당신이 고개를 돌리면 놀라지 않을 것입니다. 누군가 문제가되지는 않습니다.

panic("inconceivable") 

panic

는 항상 프로그램에 치명적입니다.
패닝에서는 발신자가 문제를 해결할 수 있다고 가정하지 않습니다..따라서 공황은 예외적 인 상황, 코드가 불가능한 코드 또는 코드 통합을 계속하는 사람에게만 사용됩니다.

Go에 예외를 포함하지 않기로 한 결정은 단순성과 직교성의 예입니다. 여러 반환 값과 간단한 규칙을 사용하여 Go는 상황이 잘못되었을 때 프로그래머가 알 수있는 문제를 해결하고 진정한 예외적 인 상황을 위해 공황 상태를 만듭니다. err를 사용


다른 방법은, 공식 위키 페이지 "Error handling and Go"에서 설명합니다.

말했다되고 있다는 기사는 "Defer, Panic, and Recover"공황 (json package, (d *decodeState) unmarshal method)를위한 실제 사례를 언급 않으며, 추가

이동 라이브러리의 규칙도 패키지 공황을 사용하는 경우이다 내부적으로는 외부 API가 여전히 명시적인 오류 반환 값을 표시합니다.

따라서 공황 상태가 엄격하게 내부적 인 경우 작동 할 수 있습니다.

2

내 개인적인 견해는 공포는 악마의 일이며 거의 사용되지 않아야한다는 것입니다.

공황 상태에있는 모든 HTTP 처리기를 패닉 상태로 감싼다는 점을 감안할 때 (stdlib가 포함 된) 많은 일들이 있기 때문에 그 공포와 그에 대처해야합니다. 귀하의 웹 서버를 무너 뜨리는 것이 적절하지 않습니다.

우리가 수행 한 작업은 우리의 오류 패키지를 우리 자신의 것으로 덮어 쓰는 것입니다. 그래서 우리가 오류를 생성 할 때 역 추적과 함께 오류 자체가 사이트에 기록되어 사용자가 거기에서 기록/추적 할 수 있습니다.

예를 들어 기본 HTTP 구현 -> https://deferpanic.com/help/exception-handling/native

나는이 방법은 당신이 당신의 케이크를 가지고/당황 복구 의존하지 않고 너무 그것을 먹을 수 있습니다 생각합니다.

관련 문제