我正在使用这个版本的 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()
,<-c
,g()
, 和k()
。但是,与评估和索引以及评估相比,这些事件的顺序未指定。x
y
所以基本上规范只保证函数调用和通信操作从左到右发生。
你的电话有参数"A"
,a
和SetAI(&a)
。无法保证第二个参数是否在传递给a
的参数之前被求值,这非常重要,因为会修改。由于无法保证顺序,因此您不能依赖首先评估哪个顺序,这两个顺序均符合规范。&a
SetAI()
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}
- 1 回答
- 0 关注
- 89 浏览
添加回答
举报
0/150
提交
取消