2017-07-21 129 views
3

我正在读取一些在github上用golang编写的代码,并且发现了非常有趣的一段代码。我将其简化为明确。在函数中返回值为空的返回值golang

func Insert(docs ...interface{}) (err error) { 
    for i := 0; i < 3; i++ { 
     err = fmt.Errorf("") 
     if err.Error()!="EOF" { 
      return 
     } 
    } 
    return err 
} 

我对这里的空回归非常困惑......它是如何工作的?他返回零作为错误或循环休息?我明白,这个问题看起来是虚构的,但我无法在go docs上找到任何有关这方面的信息......另外,我不明白我们如何返回err,也就是说,据我所知,以某种方式宣布返回。 (err错误)是否意味着我们的func中已经有了一个错误变量,如果没有指定,它将用作默认返回值?那么为什么我们在func的结尾隐含地返回err?

我会非常乐意解释。

+1

见 “命名的返回值” 中的[ “围棋之旅”(https://tour.golang.org/basics/7)和[ “有效围棋”(HTTPS ://golang.org/doc/effective_go.html#named-results) – JimB

回答

6

该函数使用“命名”返回值。在return语句

the spec:如果函数的结果类型 指定其结果参数名称

表达列表可能为空。结果参数作为普通局部变量执行 ,并且该功能可以根据需要为其分配值 。 “return”语句返回这些变量的值。

不管它们是如何宣布,所有的结果值有 初始化至零个值入境后到 函数的类型。指定结果的“return”语句会在执行任何延迟函数之前设置结果 参数。

使用命名的回报,您可以节省手动分配的局部变量一些代码,有时可能会清理杂乱的if/else语句或返回值的长列表。

func a()(x []string, err error){ 
    return 
} 

实际上只是

func a() ([]string,error){ 
    var x []string 
    var err error 
    return x,err 
} 

它有点短速记,我同意,它可能不那么明显。

命名的返回有时是需要的,因为它允许像在延迟函数内部访问它们那样的东西,但根据我可以判断,裸返回只是语法糖,并且从不被严格要求。

我经常看到的一个地方是在函数中有很多返回值的错误返回情况。

if(err != nil){ 
    return 
} 
return a,b,c,nil 

是很容易,

if(err != nil){ 
    return nil,nil,nil,err 
} 
return a,b,c,nil 

当你把它写了一堆倍。如果您将签名更改为具有其他“真实”返回值,则不必修改这些返回值。

我在我刚刚搜索的代码库中使用它们的大多数地方,它们肯定似乎隐藏了其他的气味,比如过于复杂的多用途功能,太深的if/else嵌套以及类似的东西。

+0

你可以发表一些例子,其中这种类型的声明清理如果是或类似的东西?对我来说,这种语言功能看起来像一个糟糕的设计(我来自C#) –

+2

我没有强烈的使用裸返回的参数,并且通常默认为显式。但我编辑了一些更多的考虑。 – captncraig

+0

非常感谢您的回复,现在我完全理解了这个问题! :) –

3

当你有一个命名返回值(err这里):

func Insert(docs ...interface{}) (err error) { 

这由名字创建了一个函数局部变量,如果你只需要调用return不带参数,它返回本地变量。因此,在这个功能,

return 

是一样的,并暗示,

return err 

这是详细in the tourin the spec

+0

好的,但是为什么我们使用空回归并隐式地在func结尾写回return err? –

+2

绝对没有理由。保持一致可能会更好。 – Adrian

+1

@AlexVoskresenskiy在[这个问题]的一些很好的答案(https://stackoverflow.com/questions/15089726/why-should-return-parameters-be-named) – captncraig

2

Go的返回值可能会被命名。如果是这样,它们被视为在函数顶部定义的变量。

package main 

import "fmt" 

func split(sum int) (x, y int) { 
    x = sum * 4/9 
    y = sum - x 
    return 
} 

func main() { 
    fmt.Println(split(17)) 
} 

https://tour.golang.org/basics/7