【发布时间】:2020-02-13 20:55:25
【问题描述】:
假设我有一个带状态的结构,以及该结构上的一些成员函数。 假设 struct 成员返回一个它自己类型的实例,我在该实例上调用附加函数,并将调用初始实例上的某个其他成员的结果作为参数传递。 第一次调用和参数调用之间的调用顺序是否得到保证?
(在尝试构建具有某种内部状态的“构建器”类型对象时,这种模式经常出现,例如表达式堆栈。)
package main
import (
"fmt"
)
type q struct {
val int
}
func (s *q) getVal() int {
return s.val
}
func (s *q) a() *q {
s.val += 1
return s
}
func (s *q) b(i int) int {
return i + s.val
}
func main() {
s := &q{}
// this currently prints 2
// but is that guaranteed?
fmt.Println(s.a().b(s.getVal()))
}
具体来说,s.a() 与 s.getVal() 的相对调用顺序是否得到保证?
Golang 定义了“从左到右的词汇顺序”,但仅限于单个表达式,s.a().b() 在技术上似乎与s.getVal() 不同。
它目前的行为是我想要和期望的行为,但我不知道它是否也是我可以“永远”依赖的行为。
【问题讨论】:
-
一个 goroutine 中的求值顺序是有保证的——我想不出一种语言没有。如果执行顺序未知,则程序无法运行。
-
另外,Go 1 Compatibility Promise 表示现在可以运行的程序在任何 Go 1.x 版本下都不会停止运行。改变评估行为的顺序显然会破坏这个承诺。
-
尽管值得指出的是,任何严重依赖于评估顺序的代码对于任何阅读它的开发人员来说都不必要地难以推理,并且应该重构设计以使其更容易理解并且更少容易出错。
-
是的,但是整个文档太长,无法粘贴到评论中,这就是我链接到它的原因。
标签: go method-call expression-evaluation