我有一段错误处理中间件:
func Error(next http.HandlerFunc) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
log.Error("Caught error in defer/recover middleware: ", err)
originalError := err.(struct{ OriginalError error }).OriginalError
if originalError != nil {
log.Error("Original error in defer/recover middleware: ", originalError)
}
statusCode := err.(struct{ StatusCode int }).StatusCode
if statusCode != 0 {
w.WriteHeader(statusCode)
} else {
w.WriteHeader(http.StatusInternalServerError)
}
message := err.(struct{ Message string }).Message
if message == "" {
message = "Unknown error message."
}
json.NewEncoder(w).Encode(struct {
ID string
}{
message,
})
}
}()
next.ServeHTTP(w, r)
})
}
由于它已被推迟,因此每个请求将至少运行一次,而我得到此错误:
ERRO[0009] Caught error in defer/recover middleware: runtime error: index out of range
2018/12/19 16:53:47 http: panic serving 127.0.0.1:50394: interface conversion: interface {} is runtime.errorString, not struct { OriginalError error }
goroutine 34 [running]:
net/http.(*conn).serve.func1(0xc420224000)
/usr/lib/go-1.10/src/net/http/server.go:1726 +0xd0
panic(0x700300, 0xc420232340)
/usr/lib/go-1.10/src/runtime/panic.go:502 +0x229
huru/mw.Error.func1.1(0x7a5b60, 0xc420244000)
/home/oleg/codes/huru/api/src/huru/mw/middleware.go:113 +0x309
panic(0x6fd380, 0x919c10)
/usr/lib/go-1.10/src/runtime/panic.go:502 +0x229
huru/mw.Auth.func1(0x7a5b60, 0xc420244000, 0xc42023a200)
/home/oleg/codes/huru/api/src/huru/mw/middleware.go:53 +0x4ae
net/http.HandlerFunc.ServeHTTP(0xc4201133c0, 0x7a5b60, 0xc420244000, 0xc42023a200)
/usr/lib/go-1.10/src/net/http/server.go:1947 +0x44
huru/mw.Logging.func1(0x7a5b60, 0xc420244000, 0xc42023a200)
/home/oleg/codes/huru/api/src/huru/mw/middleware.go:21 +0xcb
net/http.HandlerFunc.ServeHTTP(0xc4200117c0, 0x7a5b60, 0xc420244000, 0xc42023a200)
/usr/lib/go-1.10/src/net/http/server.go:1947 +0x44
huru/mw.Error.func1(0x7a5b60, 0xc420244000, 0xc42023a200)
/home/oleg/codes/huru/api/src/huru/mw/middleware.go:140 +0x86
net/http.HandlerFunc.ServeHTTP(0xc4200117d0, 0x7a5b60, 0xc420244000, 0xc42023a200)
/usr/lib/go-1.10/src/net/http/server.go:1947 +0x44
github.com/gorilla/mux.(*Router).ServeHTTP(0xc42013e000, 0x7a5b60, 0xc420244000, 0xc42023a200)
/home/oleg/codes/huru/api/src/github.com/gorilla/mux/mux.go:162 +0xed
net/http.serverHandler.ServeHTTP(0xc4200a5110, 0x7a5b60, 0xc420244000, 0xc42023a000)
/usr/lib/go-1.10/src/net/http/server.go:2697 +0xbc
我不知道如何解决它。
答案 0 :(得分:2)
从错误消息中,err
对象类型是runtime.errorString
而不是struct { OriginalError error }
。强制type assertion会引起恐慌。
我认为最好在类型断言期间使用第二个返回值,以检查转换过程是否成功。
if err := recover(); err != nil {
if temp, ok := err.(struct{ OriginalError error }); ok {
log.Error("Caught error in defer/recover middleware: ", err)
originalError := temp.OriginalError
if originalError != nil {
log.Error("Original error in defer/recover middleware: ", originalError)
}
}
if temp, ok := err.(struct{ StatusCode int }); ok {
statusCode := temp.StatusCode
if statusCode != 0 {
w.WriteHeader(statusCode)
} else {
w.WriteHeader(http.StatusInternalServerError)
}
}
if temp, ok := err.(struct{ Message string }); ok {
message := temp.Message
if message == "" {
message = "Unknown error message."
}
json.NewEncoder(w).Encode(struct {
ID string
}{
message,
})
}
}