考虑以下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块中有效。
也许我错过了一些考虑因素。哪种模式更受欢迎?为什么?
答案 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()