使用'逗号确定'成语还是返回指针?

时间:2014-04-28 16:43:10

标签: go idioms

考虑以下Go片段:

func sheep() (int, bool) {
    return 1, true
}

func main() {
    if dolly, ok := sheep() {
         //do something
    }
}

当我在'Effective Go'上阅读时,这被称为'逗号确定'成语。据我所知,这用于区分“发现”和“未找到”的事情。

同样可以通过以下方式实现:

type Sheep struct {}

func sheep() *Sheep {
    return &Sheep{}
}

func main() {
    if dolly := sheep(); dolly != nil {
         //do something
    }
}

后一个例子似乎达到了同样的目的,甚至可能更好。使用'逗号ok'示例,赋值仅在if块中有效。

也许我错过了一些考虑因素。哪种模式更受欢迎?为什么?

一个简短的例子:http://play.golang.org/p/ATxvle38iE

2 个答案:

答案 0 :(得分:6)

两者都是可以接受的,而且你错过了最常见的习语;返回value, error

“Effective Go”中引用的“逗号ok”惯用法通常保留给内置操作,例如从地图或通道读取,以及类型断言。

如果你需要返回一个指针不必要,不方便或者nil是有效值的值,我会使用它;但根据情况value, error可能同样好。

答案 1 :(得分:6)

在Go中,nil值可能是非常好的值。例如,nil切片(几乎)像空切片一样工作,对于用户定义的指针接收器也是如此。

由于这个原因,通常首选逗号或逗号错误习惯用法,因为它显然函数的调用者需要明确地处理错误情况(或不正常)情况。

因此,当Sheep返回值可能无效时,这些是惯用的:

func sheep() (*Sheep, bool) {...}
func sheep() (s *Sheep, ok bool) {...}  // Adding names to make it clearer
func sheep() (*Sheep, error) {...}

只有当返回值始终有效时,这才是惯用的:

func sheep() *Sheep {...}

这是Go与其他语言不同的区域,其中可以使用nil返回值来表示错误。逗号和逗号错误的Go成语巧妙地解决了这个价值数十亿美元的错误"通过使代码不处理无效返回值的nil指针看起来错误。如果您编写惯用代码,您可以立即看到错误被忽略的时间:例如,此处s2的分配会立即跳出为可疑:

s1 := sheep()
s2, _ := sheep()