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

$ go version
go version go1.18 windows/amd64

当struct A只有一个字段,而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}

推荐答案

混淆和不同输出的来源是参数的判断顺序.

看看你的例子:

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

这是一个函数call,函数值和参数在the usual order中求值:

否则,在计算表达式、赋值或return statementoperands时,所有函数调用、方法调用和通信操作都将按从左到右的词法顺序进行计算.

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

函数调用和通信的顺序为f()h()i()j()<-cg()k().However, the order of those events compared to the evaluation and indexing of 107 and the evaluation of 108 is not specified.

所以基本上规范只保证函数调用和通信

你的电话有参数"A"aSetAI(&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上try ):

A: {0 } {10 }
B: {0} {10}

或者,如果希望先计算函数调用:

a := A{}
ap := SetAI(&a)
m("A", a, ap)
b := B{}
bp := SetBI(&b)
m("B", b, bp)

这将 for each case 输出10(在Go Playground上try 此选项):

A: {10 } {10 }
B: {10} {10}

Go相关问答推荐

Go协议缓冲区导入问题

如何在GoFr中为生产和本地环境设置不同的配置?

为什么 Go 对于长度为 100k 的切片使用的内存比长度为 100k 的数组要少?

Golang Fiber Render - 将数据发送到多个布局

在golang中以JSON格式获取xwwwformurlencoded请求的嵌套键值对

使用反射在Go中递归迭代 struct 体和集合字段

在 Golang 中查看目录是否可写的跨平台方式?

Golang 到 wasm 编译使用 tinygo.使用 wasmtime 执行

最长连续重复的字符golang

当填充通道的函数调用未嵌入 goroutine 时,为什么我会遇到死锁?

上传图片失败,出现错误dial tcp: lookup api.cloudinary.com: no such host

AddE 上的 Apache Tinkerpop gremlin-go 驱动程序 Next() 返回E0903:没有剩余结果

Go:从 ssl 证书中获取 'subject/unstructeredName' 的值

Golang Getrlimit 返回与 ulimit 不同的值

GoReleaser 和 ssh-agent Github 操作:为什么无法读取用户名...终端提示已禁用?

GoLang 遍历 yaml 文件

如何排除溢出矩阵的坐标

Go 导入范围查找 protobuf 类型

gopls 为 github.com/Shopify/sarama 返回错误gopls: no packages returned: packages.Load error

如何在 Go 中使用 RSA 密钥加密和解密纯文本?