Short circuit evaluation in Go

て烟熏妆下的殇ゞ 提交于 2021-02-04 17:28:32

问题


My understanding of short circuit evaluation is that an expression is only called when needed in an if statement. Does Go follow this?

For instance, would I get better performance on average from:

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

...to this:

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

...since isValidQueryParams is a function with much more overhead than r == nil or testing the length of a map?

i.e. will the interpreter evaluate r == nil first, see it's true and not bother to evaluate the other conditions?

EDIT: Incorrectly referred to short circuit evaluation as lazy evaluation


回答1:


What you're referring to is called "short circut evaluation"—that is, the subexpressions are evaluated using the normal associativity rules only for as long as the complete result is available and evaluation of the rest of the expressions won't change it according to the rules of the binary operator(s) in question.

Go does implement short circuit evaluation of logical expressions (see the other answer).

(@icza commented: Somewhat related: there is short circuit evaluation in Go code, but Go's template engine does not use short circuit evaluation. Details: Golang template and testing for Valid fields.)

"Lazy evaluation" is completely another thing—usually implemented in the so-called "functional" programming languages, and it's not directly implemented in Go.


Having said that, I'd note that while Go does not have direct (as with the syntax and runtime) support for lazy evaluation, it may be used where needed.

For instance, you may have a goroutine reading potentially infinite number of items from a channel, and processing them in one way or another, and another goroutine—or several of them—producing these values and sending them through the channel. This way, the values only "materialize" at the receiving end no faster than they are actually ready to be handled.




回答2:


This is called short circuit evaluation. According to this tutorial, the boolean operators use this:

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

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

Here is a quick example to prove that Go uses short circuit evaluation

[…]




回答3:


Thank you to Kostix and mkrieger for their answers - they are correct, I'm referring to short circuit evaluation and not lazy evaluation.

Go does implement normal short circuit evaluation, as can be deduced with the following code:

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
}

...which will always give:

$ 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


来源:https://stackoverflow.com/questions/53722288/short-circuit-evaluation-in-go

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!