我对短路评估的理解是,仅在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")
}
......因为isValidQueryParams
是比r == nil
开销更大的函数,或者测试地图的长度?
即解释器会首先评估r == nil,看到它是正确的,而不用费心评估其他条件吗?
编辑:错误地将短路评估称为惰性评估
答案 0 :(得分:5)
您指的是“短循环评估”,也就是说,仅在可获得完整结果的情况下,才使用正常的关联性规则评估子表达式,而不会评估其余的表达式根据相关二进制运算符的规则进行更改。
Go确实实现了逻辑表达式的短路评估(请参见the other answer)。
(@ icza评论:有点相关:Go代码中有短路评估,但是Go的模板引擎不使用短路评估。详细信息:Golang template and testing for Valid fields。)
“惰性评估”完全是另一回事-通常以所谓的“功能性”编程语言实现,而并非直接在Go中实现。
话虽如此,我要指出,尽管Go不支持 direct (与语法和运行时一样)对惰性求值的支持,但可以在需要的地方使用它。
例如,您可能有一个goroutine从通道中读取可能无数的项目,并以一种或另一种方式处理它们,而另一个goroutine(或其中的几个)产生这些值并通过通道发送它们。这样,这些值仅在接收端“实现”,不会比实际准备好要快。
答案 1 :(得分:4)
这称为短路评估。根据{{3}},布尔运算符使用以下代码:
尽管在this tutorial中没有明确 声明Go使用短路评估,它确实提到了
逻辑运算符适用于布尔值,并产生与操作数相同类型的结果。评估正确的操作数 有条件的。
这是一个简单的例子,证明Go使用短路评估
[…]
答案 2 :(得分:4)
感谢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 called\n", 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