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

我正在使用这个版本的 Go:


$ go version

go version go1.18 windows/amd64

当structA只有一个字段和B有两个或以上字段时结果不同,而且只有当参数类型是interface时才会出现这种情况。


我不确定这是否是一个错误:


package main


import (

    "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}


哆啦的时光机
浏览 103回答 1
1回答

桃花长相依

混淆和不同输出的根源是参数的评估顺序。看看你的例子:m("A",&nbsp;a,&nbsp;SetAI(&a))这是一个函数调用,函数值和参数按通常的顺序求值:否则,在计算表达式、赋值或返回语句的操作数时,所有函数调用、方法调用和通信操作均按从左到右的词汇顺序进行计算。例如,在(函数局部)赋值y[f()],&nbsp;ok&nbsp;=&nbsp;g(h(),&nbsp;i()+x[j()],&nbsp;<-c),&nbsp;k()函数调用和通信的顺序为f(),&nbsp;h(),&nbsp;i(),&nbsp;j(),&nbsp;<-c,&nbsp;g(), 和k()。但是,与评估和索引以及评估相比,这些事件的顺序未指定。xy所以基本上规范只保证函数调用和通信操作从左到右发生。你的电话有参数"A",a和SetAI(&a)。无法保证第二个参数是否在传递给a的参数之前被求值,这非常重要,因为会修改。由于无法保证顺序,因此您不能依赖首先评估哪个顺序,这两个顺序均符合规范。&aSetAI()SetAI()a如果通过复制 struct&nbsp;before使评估显式,您会得到相同的结果:a := A{}aCopy := am("A", aCopy, SetAI(&a))b := B{}bCopy := bm("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}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go