Go中的短路评估

Short circuit evaluation in 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")
}

...因为 isValidQueryParams 是一个开销比 r == nil 或测试地图长度多得多的函数?

即解释器是否会首先评估 r == nil,看到它是真的而不去评估其他条件?

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

这称为短路评估。根据 this tutorial,布尔运算符使用此:

Although in the Go language specification it does not explicitly state that Go uses short circuit evaluation, it does mention that

Logical operators apply to boolean values and yield a result of the same type as the operands. The right operand is evaluated conditionally.

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

[…]

您所指的是 "short circut evaluation"——也就是说,仅在完整结果可用且对其余表达式的求值成功时,才使用正常的关联性规则对子表达式求值'根据相关二元运算符的规则更改它。

Go 确实实现了逻辑表达式的短路评估(参见 )。

(@icza评论:有点相关:Go代码中有short circuit evaluation,但是Go的模板引擎没有使用short circuit evaluation。详情:。)

"Lazy evaluation"完全是另外一回事——通常在所谓的"functional"编程语言中实现,而不会直接在Go中实现。


话虽如此,我会注意到虽然 Go 没有 direct(与语法和运行时一样)支持惰性求值,但可以在需要的地方使用它。

例如,您可能有一个 goroutine 从通道读取可能无限数量的项目,并以一种或另一种方式处理它们,而另一个 goroutine(或其中的几个)产生这些值并通过通道发送它们.这样,接收端的值仅 "materialize" 不会比实际准备好处理的速度更快。

感谢 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