Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get error message in a string in golang?

Tags:

go

I referred this question - os.Error - string value (Golang), but that is not working in my case.

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 
}

In that err I need the error message that is thrown, e.g. if the parsing logic fails, it is throwing an error automatically. That is the error I need to catch. I am showing this only for example - whatever the runtime exception is, I need to catch it and pass as err in the return.

How to achieve that?

like image 844
shanmugharaj Avatar asked Mar 04 '14 11:03

shanmugharaj


People also ask

How do you check errors in Golang?

Errors can be returned as nil , and in fact, it's the default, or “zero”, value of on error in Go. This is important since checking if err != nil is the idiomatic way to determine if an error was encountered (replacing the try / catch statements you may be familiar with in other programming languages).

What is err != Nil in Golang?

if err != nil { return err } > is outweighed by the value of deliberately handling each failure condition at the point at which they occur. Key to this is the cultural value of handling each and every error explicitly.

How do you wrap errors in Go?

In Go 1.13, though, Go added support for wrapping and unwrapping errors as part of the standard library by adding the errors. Unwrap function and the %w verb for the fmt. Errorf function. In this section, you'll update your program to use the %w verb to wrap errors with more information, and you'll then use errors.


Video Answer


3 Answers

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

like image 131
Intermernet Avatar answered Sep 23 '22 08:09

Intermernet


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
}
like image 25
metakeule Avatar answered Sep 22 '22 08:09

metakeule


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
}
like image 6
0xInfection Avatar answered Sep 22 '22 08:09

0xInfection