【问题标题】:If error is not nil why return both err and nil?如果错误不是 nil,为什么要同时返回 err 和 nil?
【发布时间】:2018-08-24 15:03:04
【问题描述】:

我正在关注 golang wiki instruction 并发现这令人困惑:

func loadPage(title string) (*Page, error) {
    filename := title + ".txt"
    body, err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, err
    }
    return &Page{Title: title, Body: body}, nil
}

如果 err 不等于 nil,为什么返回 nil?

难道不应该是:

if err != nil {
    return err
}

就像golang errors and values中描述的那样?

【问题讨论】:

    标签: go return-value


    【解决方案1】:

    该函数返回两件事:一个页面(指针)和一个错误。如果发生错误,则没有要返回的页面,因此返回的第一个值是nil。返回的第二个值是错误,err,应该如此。

    【讨论】:

    • 谢谢@Leon。所以如果函数返回 x 个东西,对于每个 if 语句,我应该返回 x vars?
    • 是的,每当您从函数中return 时,您必须返回函数返回的所有值。
    【解决方案2】:

    The Go Programming Language Specification

    The zero value

    当为变量分配存储空间时,无论是通过声明 或调用 new,或在创建新值时,通过 复合文字或 make 调用,并且没有显式初始化 提供,变量或值被赋予默认值。每个元素 这样一个变量或值的类型被设置为零值: 布尔值为 false,数字类型为 0,字符串为 "",nil 为 指针、函数、接口、切片、通道和映射。这个 初始化是递归完成的,因此例如 如果未指定值,则结构数组的字段将归零。


    由于错误,没有返回有效值,所以我们返回零值,在这种情况下恰好是nil(对于指针值)。

    【讨论】:

      【解决方案3】:

      在 loadpage 函数中,您返回两个值,一个是指向 Page 的指针,另一个是错误。

      func loadPage(title string) (*Page, error) {
          filename := title + ".txt"
          body, err := ioutil.ReadFile(filename)
          if err != nil {
              return nil, err
          }
          return &Page{Title: title, Body: body}, nil
      }
      

      这就是代码中有错误并且不等于nil的原因。然后返回错误。但是由于您还需要返回 Page 它也应该是 nil ,因为它表示指针的零值。这表明 Page 的值为空。

      return &Page{Title: title, Body: body}, nil
      

      但是如果没有错误,那么您将再次返回两个值,一个是 Page 结构的地址,其值分配给 Page 字段,但 nil 表示错误。

      如果一个类型的值不包含任何值。它应该用零值初始化,即

      false 表示布尔值,0 表示数字类型,"" 表示字符串,nil 表示 指针、函数、接口、切片、通道和映射。

      一个或多个返回值可以在“return”语句中明确列出。每个表达式必须是单值的,并且可以分配给函数结果类型的相应元素。

      func complexF1() (re float64, im float64) {
          return -7.0, -4.0
      }
      

      “return”语句中的表达式列表可能是对多值函数的一次调用。效果就像从该函数返回的每个值都分配给具有相应值类型的临时变量,然后是列出这些变量的“return”语句,此时适用前一种情况的规则。

      func complexF2() (re float64, im float64) {
          return complexF1()
      }
      

      注意:

      不管它们是如何声明的,所有的结果值都是 在进入 功能。指定结果的“return”语句设置结果 执行任何延迟函数之前的参数。

      查看 Return statements 的 Golang 规范

      【讨论】:

      • 感谢@Himanshu,所以如果有错误,我会返回函数应该返回的所有变量。我的看法是:if (err) throw err else return (vars supposed to return)。所以在 Go 中,if 语句后面的行不是else
      • @Viet 其实就像返回多个值一样。您可以根据需要设置任意数量的值。但是假设如果有错误,您应该返回错误并为其他变量设置零值。我在回答中提到了应该为不同类型返回哪些值作为零值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-26
      • 1970-01-01
      • 2013-03-14
      • 1970-01-01
      • 2014-11-11
      • 2021-12-03
      • 1970-01-01
      相关资源
      最近更新 更多