【问题标题】:Short circuit evaluation in GoGo中的短路评估
【发布时间】:2019-05-12 08:01:17
【问题描述】:

我对短路评估的理解是,只有在 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,看看它是真的,而不费心去评估其他条件吗?

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

【问题讨论】:

  • 我认为惰性求值通常是指一个变量,其值在被访问之前不会被计算或获取(例如从数据库或 API)。
  • 有点相关:Go 代码中存在短路评估,但 Go 的模板引擎不使用短路评估。详情:Golang template and testing for Valid fields
  • @icza,谢谢,包括在内。

标签: go short-circuiting


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    虽然在Go language specification 中并没有明确表示 声明 Go 使用短路评估,它确实提到了

    逻辑运算符适用于布尔值并产生与操作数相同类型的结果。计算右操作数 有条件的。

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

    […]

    【讨论】:

      【解决方案3】:

      您所指的内容称为“短路评估”——也就是说,仅在完整结果可用且其余表达式的评估不可用时,才使用正常关联规则评估子表达式根据相关二元运算符的规则更改它。

      Go 确实实现了逻辑表达式的短路求值(参见 the other answer)。

      (@icza 评论:有点相关:Go 代码中有短路求值,但 Go 的模板引擎不使用短路求值。详情:Golang template and testing for Valid fields。)

      “惰性求值”完全是另一回事——通常在所谓的“函数式”编程语言中实现,而不是直接在 Go 中实现。


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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-14
        • 2017-01-21
        • 2012-02-10
        • 2010-12-21
        • 1970-01-01
        • 2013-05-21
        相关资源
        最近更新 更多