【问题标题】:How to get error message in a string in golang?如何在golang的字符串中获取错误消息?
【发布时间】:2014-03-04 11:40:56
【问题描述】:

我提到了这个问题 - os.Error - string value (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 传递。

如何实现?

【问题讨论】:

  • t.TransObject["qty"].(map[string] interface{})["ticket fv"].(float64) 之类的代码指出了正确建模域的一些重大问题。也许您可以尝试一个没有空接口的解决方案并键入不需要大量恐慌/延迟/恢复魔法的断言?
  • 补充一点:将错误作为字符串返回不是一个好习惯。创建您自己的错误类型type MyError error 并给它一个方法:func (m *MyError) Error() string - 这就是满足error 接口所需的全部内容。阅读更多信息:blog.golang.org/error-handling-and-go

标签: go


【解决方案1】:

使用errors 包创建新错误。

err = errors.New("an error")

可以通过访问err.Error() 或使用fmt 包函数(例如fmt.Println(err))将返回的错误视为字符串。

除非你真的知道你在做什么,否则不要使用recover。返回所有错误并在它们出现时处理它们是惯用的。

有关详细信息,请参阅 Go 博客上的 Error handling and GoDefer, Panic and Recover

编辑:

重新阅读您的问题,您似乎正试图从可能失败的type assertions 中恢复过来。在这种情况下,建议使用“comma, ok”成语(在文档前面链接的部分中提到),它(稍微解释为更笼统)意味着:

“如果类型断言失败,[接收者变量]将仍然存在并且是类型[无论断言什么],但它将具有零值......”

通过类型断言测试interface{} 是否实际上是float64 的简单示例,如果失败则生成自定义错误(而不是恐慌):

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)
    }
}

将打印:

1024.000000 是 float64
无法断言“foo”是 float64。

Playground

【讨论】:

  • 感谢您的回复。我会创造错误,你说它很好。在某些情况下,如果我需要恢复意味着我将如何在字符串中出现错误?我的要求是记录系统生成的错误。请向我提出任何想法。
  • @shan error 是一个interface that implements Error() string。调用此方法来检索消息。或者,fmt 包可以处理error 值并自动打印消息,因此您可以简单地使用fmt.Println(err) 来打印消息。
  • @nemo 实际上,如果我尝试 str.Error() 它会说 str.Error undefined (type interface {} has no field or method Error) 这个错误。对不起,我无法弄清楚..
  • 问题是 str 是一个恢复对象。所以我猜它不会出现。我对这种语言很陌生并且搞砸了。
  • @shan recover 给你一个interface{} 值,一个可以容纳任何值的值。您必须断言该值是否实现了error 接口。之后,您可以致电Error()。见type assertions
【解决方案2】:

我认为这可以满足您的需求:

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
}

【讨论】:

    【解决方案3】:

    添加到@intermernet's answer,如果您使用errors.New() 创建自定义错误消息,您可能需要检查创建的特定错误消息。此外,也可以以相同的方式检查任何其他类型的错误消息。只需将fmt.Sprintf() 函数与strings.Contains() 一起使用即可。

    您可以非常简单地做到这一点:

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

    或者更好地使用strings.Contains():

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

    【讨论】:

      猜你喜欢
      • 2020-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-25
      相关资源
      最近更新 更多