0

我不明白处理恐慌的最佳方法是什么。我可以自己写panic("bad data or empty source"),我会根据输出确定代码在这个确切的地方失败,但是如何处理在不是我的方法中生成的恐慌。

现在我有这样的错误:

C:/gocode/src/github.com/revel/revel/panic.go:26 (0x4975a4) handleInvocationPanic: c.Response.Out.Write(debug.Stack()) 
C:/gocode/src/github.com/revel/revel/panic.go:12 (0x4b60ca) PanicFilter.func1: handleInvocationPanic(c, err) 
c:/go/src/runtime/asm_amd64.s:437 (0x45cc75) call32: CALLFN(·call32, 32) 
c:/go/src/runtime/panic.go:423 (0x42ec17) gopanic: reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz)) 
C:/gocode/src/github.com/revel/revel/intercept.go:93 (0x4b6061) InterceptorFilter.func1: panic(err)
c:/go/src/runtime/asm_amd64.s:437 (0x45cc75) call32: CALLFN(·call32, 32)
c:/go/src/runtime/panic.go:423 (0x42ec17) gopanic: reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
c:/go/src/runtime/panic.go:42 (0x42d280) panicmem: panic(memoryError)
c:/go/src/runtime/signal_windows.go:161 (0x44233d) sigpanic: panicmem()
C:/gocode/src/github.com/oculus/libs/funcs.go:13 (0x4e0ca5) GetDatesInRange: fmt.Println(err.Error())
C:/gocode/src/github.com/oculus/rest/app/controllers/kpi.go:97 (0x4e3b2f) KpiCtrl.GetNoagg: dates, errors := libs.GetDatesInRange(request.Filters.DayStart, request.Filters.DayEnd) :97 (0x4e9f12)
c:/go/src/runtime/asm_amd64.s:437 (0x45cc75) call32: CALLFN(·call32, 32)
c:/go/src/reflect/value.go:432 (0x471591) Value.call: call(frametype, fn, args, uint32(frametype.size), uint32(retOffset))
c:/go/src/reflect/value.go:300 (0x470258) Value.Call: return v.call("Call", in)
C:/gocode/src/github.com/revel/revel/invoker.go:36 (0x496e51) ActionInvoker: resultValue = methodValue.Call(methodArgs)[0]
C:/gocode/src/github.com/revel/revel/compress.go:47 (0x487f89) CompressFilter: fc[0](c, fc[1:])
C:/gocode/src/github.com/revel/revel/intercept.go:103 (0x4954b9) InterceptorFilter: fc[0](c, fc[1:])
C:/gocode/src/github.com/oculus/rest/app/init.go:37 (0x4e2366) glob.func1: fc[0](c, fc[1:]) // Execute the next filter stage.
C:/gocode/src/github.com/revel/revel/i18n.go:155 (0x4947a3) I18nFilter: fc[0](c, fc[1:])
C:/gocode/src/github.com/revel/revel/validation.go:191 (0x4ae27d) ValidationFilter: fc[0](c, fc[1:])
C:/gocode/src/github.com/revel/revel/flash.go:46 (0x490ee7) FlashFilter: fc[0](c, fc[1:])
C:/gocode/src/github.com/revel/revel/session.go:149 (0x4a914c) SessionFilter: fc[0](c, fc[1:])
C:/gocode/src/github.com/revel/revel/params.go:133 (0x499116) ParamsFilter: fc[0](c, fc[1:])
C:/gocode/src/github.com/revel/revel/filterconfig.go:208 (0x490a64) FilterConfiguringFilter: fc[0](c, fc[1:])
C:/gocode/src/github.com/revel/revel/router.go:474 (0x4a61e6) RouterFilter: fc[0](c, fc[1:])
C:/gocode/src/github.com/revel/revel/panic.go:15 (0x4972c8) PanicFilter: fc[0](c, fc[1:])
C:/gocode/src/github.com/revel/revel/watcher.go:232 (0x4b512d) glob.func31: fc[0](c, fc[1:])
C:/gocode/src/github.com/revel/revel/server.go:50 (0x4a6d95) handleInternal: Filters[0](c, Filters[1:])
C:/gocode/src/github.com/revel/revel/server.go:38 (0x4a68f6) handle: handleInternal(w, r, nil)
c:/go/src/net/http/server.go:1422 (0x57cfe1) HandlerFunc.ServeHTTP: f(w, r)
c:/go/src/net/http/server.go:1862 (0x57f285) serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
c:/go/src/net/http/server.go:1361 (0x57ca85) (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
c:/go/src/runtime/asm_amd64.s:1721 (0x45f121) goexit: BYTE  $0x90   // NOP

我应该如何与他们合作,或者如何确定问题出在哪里。这对我来说不是有益的。

4

2 回答 2

4

In Go you have the possibility to recover from panic, which does contain the panic error message. After recovering you may analyze the issue why the panic is happening. To recover from panic you can use the defer statement which as the name implies, defers execution of the statement. This means that you can skip some events to hang up the system, which is not quite a good solution. The best solution is to capture the errors and handle them adequately. If the error happens on some third party framework this should be addressed by their creators. If not you should check why your code is panicking.

Here a code snippet for panic recover:

defer func() {
    if err := recover(); err != nil {
        fmt.Printf("Recovered from panic. %s", err)
    }
}()

And here is a simple example of how you can use the build in panic and recovery methods:

package main

import "fmt"

func badCall() {
    panic("Bad call happend!")
}

func test() {
    defer func() {
        if err := recover(); err != nil {
            fmt.Printf("Panicking %s\n\r" , err)
        }
    }()

    badCall()
    fmt.Println("This is never executed!!")
}

func main() {
    fmt.Println("Start testing")
    test()
    fmt.Println("End testing")
}

http://play.golang.org/p/Uz9W76SfRT

If recover is called inside a deferred function, the stack stops unwinding and recover returns the value (as an interface{}!) that was passed to panic. This means that you can pass an interface as an argument to the panic method, like:

type ParseError struct {
    Index int    // The index into the space-separated list of words.
    Word  string // The word that generated the parse error.
    Error error  // The raw error that precipitated this error, if any.
}

// String returns a human-readable error message.
func (e *ParseError) String() string {
    return fmt.Sprintf("pkg: error parsing %q as int", e.Word)
}

// ... some code
if err != nil {
    panic(&ParseError{idx, field, err})
}
// ... some code

Then you can analyze the passed interface in the deferred statement.

Read this article: https://github.com/golang/go/wiki/PanicAndRecover

于 2016-02-11T13:19:58.403 回答
4

您可以使用这段代码并将其放在每个函数中

defer func() {
  if err := recover(); err != nil {
    fmt.Println("Panic Occured and Recovered in, Error Info: ", err)
  }
}()

试试这个它会为你工作。

于 2016-02-11T13:24:23.423 回答