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
我对短路评估的理解是,仅在 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