Go中的短路评估



我对短路求值的理解是,只有在if语句中需要时才调用表达式。Go遵循这个吗?

例如,我会从中获得更好的平均性能吗

if !isValidQueryParams(&queries) || r == nil || len(queries) == 0 {
return "", fmt.Errorf("invalid querystring")
}

到此:

if r == nil || len(queries) == 0 || !isValidQueryParams(&queries) {
return "", fmt.Errorf("invalid querystring")
}

因为CCD_ 1是一个比CCD_ 2开销大得多的函数,或者测试映射的长度?

也就是说,解释器会先评估r==nil,看看它是真的,而不去评估其他条件吗?

编辑:错误地将短路评估称为延迟评估

感谢Kostix和mkrieger的回答——他们是正确的,我指的是短路评估,而不是懒惰评估。

Go确实实现了正常的短路评估,可以用以下代码推断:

package main
import "fmt"
func main() {
for i := 0; i < 10; i++ {
if testFunc(1) || testFunc(2) {
// do nothing
}
}
}
func testFunc(i int) bool {
fmt.Printf("function %d calledn", i)
return true
}

它将始终给出:

$ function 1 called
$ function 1 called
$ function 1 called
$ function 1 called
$ function 1 called
$ function 1 called
$ function 1 called
$ function 1 called
$ function 1 called
$ function 1 called

这被称为短路评估。根据本教程,布尔运算符使用以下内容:

尽管在Go语言规范中它没有明确声明Go使用短路评估,它确实提到

逻辑运算符应用于布尔值,并产生与操作数类型相同的结果。计算右侧操作数有条件地

这里有一个快速的例子来证明Go使用短路评估

[…]

您所指的是所谓的"短路求值"——也就是说,只有在完整结果可用的情况下,才使用正常的关联性规则来求值子表达式,并且根据所讨论的二进制运算符的规则,对其余表达式的求值不会改变它。

Go确实实现了逻辑表达式的短路求值(请参阅另一个答案(。

(@icza评论道:有些相关:Go代码中存在短路评估,但Go的模板引擎不使用短路评估。详细信息:Golang模板和有效字段测试。(

"懒惰评估"完全是另一回事——通常用所谓的"函数式"编程语言实现,而不是直接在Go中实现。


话虽如此,我要注意的是,虽然Go没有直接(与语法和运行时一样(对延迟求值的支持,但它可以在需要的地方使用。

例如,您可能有一个goroutine从一个通道读取可能无限多的项目,并以这样或那样的方式处理它们,而另一个gorroutine——或其中的几个——产生这些值并通过通道发送它们。这样,值只会在接收端"实现",速度不会快于实际准备处理的速度。

最新更新