为了账号安全,请及时绑定邮箱和手机立即绑定

函数参数的求值顺序是什么?

函数参数的求值顺序是什么?

Go
哆啦的时光机 2022-11-28 10:42:56
我正在使用这个版本的 Go:$ go versiongo version go1.18 windows/amd64当structA只有一个字段和B有两个或以上字段时结果不同,而且只有当参数类型是interface时才会出现这种情况。我不确定这是否是一个错误:package mainimport (    "fmt")func main() {    a := A{}    m("A", a, SetAI(&a))    b := B{}    m("B", b, SetBI(&b))}type A struct {    I int    S string}type B struct {    I int}func SetAI(a *A) A {    a.I = 10    return *a}func SetBI(b *B) B {    b.I = 10    return *b}func m(name string, arg1, arg2 interface{}) {    fmt.Println(name+":", arg1, arg2)}我期待这个输出:A: {10} {10}B: {10} {10}相反,我得到了这个:A: {0 } {10 }B: {10} {10}
查看完整描述

1 回答

?
桃花长相依

TA贡献1860条经验 获得超8个赞

混淆和不同输出的根源是参数的评估顺序。

看看你的例子:

m("A", a, SetAI(&a))

这是一个函数调用,函数值和参数按通常的顺序求值:

否则,在计算表达式、赋值或返回语句的操作数时,所有函数调用、方法调用和通信操作均按从左到右的词汇顺序进行计算。例如,在(函数局部)赋值

y[f()], ok = g(h(), i()+x[j()], <-c), k()

函数调用和通信的顺序为f()h()i()j()<-cg(), 和k()但是,与评估和索引以及评估相比,这些事件的顺序未指定。xy

所以基本上规范只保证函数调用和通信操作从左到右发生。

你的电话有参数"A",aSetAI(&a)。无法保证第二个参数是否在传递给a的参数之前被求值,这非常重要,因为会修改。由于无法保证顺序,因此您不能依赖首先评估哪个顺序,这两个顺序均符合规范。&aSetAI()SetAI()a

如果通过复制 struct before使评估显式,您会得到相同的结果:

a := A{}

aCopy := a

m("A", aCopy, SetAI(&a))

b := B{}

bCopy := b

m("B", bCopy, SetBI(&b))

这将输出(在Go Playground上尝试):


A: {0 } {10 }

B: {0} {10}

或者,如果您希望首先评估函数调用:


a := A{}

ap := SetAI(&a)

m("A", a, ap)

b := B{}

bp := SetBI(&b)

m("B", b, bp)

这将为每个案例输出(在Go Playground10上试试这个):


A: {10 } {10 }

B: {10} {10}


查看完整回答
反对 回复 2022-11-28
  • 1 回答
  • 0 关注
  • 89 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信