Go中的短路评估

时间:2018-12-11 10:37:45

标签: go short-circuiting

我对短路评估的理解是,仅在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,看到它是正确的,而不用费心评估其他条件吗?

编辑:错误地将短路评估称为惰性评估

3 个答案:

答案 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