如何得到错误消息在一个字符串在 golang?

我提到了这个问题-错误字符串值(Golang),但这在我的情况下不起作用。

func (t Trans) TicketQty() (intQty int, err string) {
defer func() {
str := recover()
if(str != nil){
err = "an error"
}
}()
Qty := t.TransObject["qty"].(map[string] interface{})["ticket fv"].(float64)
intQty = 10
return
}

err中,我需要抛出的错误消息,例如,如果解析逻辑失败,它将自动抛出一个错误。这就是我需要纠正的错误。我只是举例说明这一点——无论运行时异常是什么,我都需要捕获它并在返回中作为 err传递。

如何做到这一点?

156929 次浏览

Use the errors package to create new errors.

err = errors.New("an error")

The returned error can be treated as a string by either accessing err.Error(), or using the fmt package functions (for example fmt.Println(err)).

Don't use recover unless you really know what you're doing. It's idiomatic to return all errors, and to deal with them when they arise.

See Error handling and Go, and Defer, Panic and Recover on the Go blog for more info.

EDIT:

Re-reading your question, it looks like you're trying to recover from possible failed type assertions. In this instance it's recommended to use the "comma, ok" idiom (mentioned in the previously linked section of the docs), which (slightly paraphrased to be more general) means:

"If the type assertion fails, [the receiver variable] will still exist and be of type [whatever was asserted], but it will have the zero value..."

Simple example to test if an interface{} is actually a float64 through type assertion, and produce a custom error if it fails (instead of panicking):

package main


import (
"errors"
"fmt"
)


// assertFloat64 attempts a type assertion to float64.
// It returns a custom error if it fails.
func assertFloat64(n interface{}) error {
// Type assertion. Is n float64?
f, ok := n.(float64)
// If yes,
if ok {
// print the result
fmt.Printf("%f is float64\n", f)
// and return nil error.
return nil
}
// Else return our custom error
return errors.New(fmt.Sprintf("could not assert that \"%v\" is float64.\n", n))
}


func main() {
// Successful
// 1024.0 is float64
err := assertFloat64(1024.0)
if err != nil {
fmt.Println(err)
}


// Failure
// "foo" isn't float64
err = assertFloat64("foo")
if err != nil {
fmt.Println(err)
}
}

Will print:

1024.000000 is float64
could not assert that "foo" is float64.

Playground

I think this would do what you want:

func (t Trans) TicketQty() (intQty int, err error) {
defer func() {
ex := recover()
if(ex != nil){
// "%v" prints the value of ex
// for strings, it is the string, for errors .Error() method, for Stringer the .String() etc
// Errorf returns an error instead of a string
err = fmt.Errorf("%v", ex)
}
}()
... // do your thing
return
}

Adding to @intermernet's answer, if you are creating custom error messages using errors.New(), you might want to keep a check out for the specific error message created. Additionally any other kind of error messages too can be checked in the same manner. Just use the fmt.Sprintf() function with strings.Contains().

You can do this very simply:

if fmt.Sprint(err) == "My Custom Error" {
// do something
}

Or better use strings.Contains():

if strings.Contains(fmt.Sprint(err), "Custom Error") {
// do something
}

NOTE: You can also use err.Error() which returns a string representation of the error instead of fmt.Sprint(err).