在Go中自定义错误处理

huangapple go评论124阅读模式
英文:

Custom error handling in Go

问题

我一直在阅读这篇博客文章,但我仍然不确定我应该如何确切地做到从我的函数中返回和处理自定义错误。

这是我目前正在做的:

  1. func doSomething() int {
  2. x := 0
  3. // 对x进行一些操作。
  4. ...
  5. if 发生了一些不好的事情 {
  6. return -1
  7. }
  8. if 发生了另一些不好的事情 {
  9. return -2
  10. }
  11. return x
  12. }

这是我想要做的:

  1. func doSomething() int, 错误类型 {
  2. ...
  3. if 发生了一些不好的事情 {
  4. return ?, 错误
  5. }
  6. if 发生了另一些不好的事情 {
  7. return ?, 错误2
  8. }
  9. return x, nil
  10. }

但我不确定如何以及用什么替换那些问号。

英文:

I've been reading this blog post but I'm still not convinced I know exactly what to do to get custom errors that I can return from my functions and handle outside of them.

This is what I'm currently doing:

  1. func doSomething() int {
  2. x := 0
  3. // Do something with x.
  4. ...
  5. if somethingBadHappened {
  6. return -1
  7. }
  8. if somethingElseBadHappened {
  9. return -2
  10. }
  11. return x
  12. }

This is what I'd like to be doing:

  1. func doSomething() int, ? {
  2. ...
  3. if somethingBadHappened {
  4. return ?, err
  5. }
  6. if somethingElseBadHappened {
  7. return ?, err2
  8. }
  9. return x, nil
  10. }

But I'm not exactly sure how, and what to replace those question marks with.

1: http://blog.golang.org/2011/07/error-handling-and-go.html "this blog post"

答案1

得分: 8

你不一定需要返回一个整数,如果你不想的话。你可以这样做:

  1. func doSomething() error {
  2. ...
  3. if somethingBadHappened {
  4. return errors.New("something bad happened")
  5. }
  6. if somethingElseBadHappened {
  7. return errors.New("something else bad happened")
  8. }
  9. return nil
  10. }

或者如果你想返回整数

  1. func doSomething() (int, error) {
  2. ...
  3. if somethingBadHappened {
  4. return -1, errors.New("something bad happened")
  5. }
  6. if somethingElseBadHappened {
  7. return -2, errors.New("something else bad happened")
  8. }
  9. return x, nil
  10. }

确保在顶部导入 "errors"。

如果你想测试是否出现了错误,你可以这样做

  1. x, err := doSomething()
  2. if err != nil {
  3. log.Println(err)
  4. }
英文:

You don't really need to return an int if you don't want to. You can do something like:

  1. func doSomething() error {
  2. ...
  3. if somethingBadHappened {
  4. return errors.New("something bad happened")
  5. }
  6. if somethingElseBadHappened {
  7. return errors.New("something else bad happened")
  8. }
  9. return nil
  10. }

or if you want to return ints

  1. func doSomething() (int, error) {
  2. ...
  3. if somethingBadHappened {
  4. return -1, errors.New("something bad happened")
  5. }
  6. if somethingElseBadHappened {
  7. return -2, errors.New("something else bad happened")
  8. }
  9. return x, nil
  10. }

be sure to import "errors" at the top.

If you want to test whether you got an error, you can do

  1. x, err := doSomething()
  2. if err != nil {
  3. log.Println(err)
  4. }

答案2

得分: 4

我会将代码部分翻译成以下内容:

  1. func doSomething() (r int, err error) {
  2. ...
  3. if somethingBadHappened {
  4. err = err1 // 任何满足 `error` 接口的错误
  5. return
  6. }
  7. if somethingElseBadHappened {
  8. err = err2 // 同上
  9. return
  10. }
  11. return x, nil
  12. }

换句话说,在调用处,如果 err != nil,按惯例*忽略、不使用或依赖其他返回值,所以不需要关心上面的 r 是否已经被赋予了某个中间值。

(*)在第一个近似中,即如果没有另外说明的情况下。例如,io.Reader 明确声明它可以同时返回 err == io.EOF 和有效数据:

当 Read 在成功读取 n > 0 个字节后遇到错误或文件结束条件时,它会返回已读取的字节数。它可以在同一次调用中返回(非 nil)错误,也可以在后续调用中返回错误(和 n == 0)。这种一般情况的一个实例是,在输入流的末尾返回非零字节数的 Reader 可能返回 err == EOF 或 err == nil。下一次 Read 应该返回 0, EOF。

英文:

I would turn

  1. func doSomething() int, ? {
  2. ...
  3. if somethingBadHappened {
  4. return ?, err
  5. }
  6. if somethingElseBadHappened {
  7. return ?, err2
  8. }
  9. return x, nil
  10. }

into

  1. func doSomething() (r int, err error) {
  2. ...
  3. if somethingBadHappened {
  4. err = err1 // Whatever satisfies the `error` interface
  5. return
  6. }
  7. if somethingElseBadHappened {
  8. err = err2 // dtto
  9. return
  10. }
  11. return x, nil
  12. }

IOW, at the call site it is idiomatic* to ignore, never use or rely on, any other returned value if err != nil, so just don't care if r above has had been assigned some intermediate value or not.

(*) In the first approximatiom, i.e. if not stated otherwise. E.g. an io.Reader explicitly declares it can return both err == io.EOF and valid data at the same time:

> When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-nil) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == EOF or err == nil. The next Read should return 0, EOF regardless.

huangapple
  • 本文由 发表于 2013年3月17日 22:48:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/15462074.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定