我在试着了解围棋的内部 struct .请考虑以下代码

a,b := 10,5
b,a = a,b

上面的代码完美地交换了2个数字,a变成了5,b变成了10.我不能理解这是如何工作的.考虑第二行代码,如果a先赋给b,那么b应该是10,现在如果我们把b赋给a,那么a不应该也是10吗?

请帮我了解一下这是怎么回事

谢谢

推荐答案

TL;DR:反汇编表明CPU必须足够智能,能够看到正在发生的事情,并使用寄存器来避免覆盖内存中的现有值.


这个问题让我对golang 有了更多的了解,所以谢谢!

要弄清楚编译器是如何生成本机代码的,我们需要查看它生成的汇编代码,这些代码被链接器转换为机器码.

我写了一个小围棋程序来帮助解决这个问题:

package main

import "fmt"

func main() {
    fmt.Println(myfunction())
}

func myfunction() []int {
    a, b := 10, 5
    b, a = a, b
    return []int{a, b}
}

然后使用go tool compile -S > swap.s,我对myfunction使用了CTRL-F(这就是这个名字的意义:易于搜索),并找到了这四行,这四行对应于Go代码中myfunction的前两行:(注意这是我的64位机器;其他架构(如32位)的输出会有所不同)

0x0028 00040 (swap.go:10)   MOVQ    $10, CX         ; var a = 10
0x002f 00047 (swap.go:10)   MOVQ    $5, AX          ; var b = 5
0x0036 00054 (swap.go:11)   MOVQ    CX, "".b+16(SP) ; copy a to *b+16
0x003b 00059 (swap.go:11)   MOVQ    AX, "".a+24(SP) ; copy b to *a+24 

围棋的反汇编对调试非常有帮助:d

看一下the Golang docs on asm,我们可以看到汇编器使用间接的方式来变化值.

当程序运行时,CPU足够智能,可以看到正在发生的事情,并使用寄存器来避免覆盖现有值.

Here's the full disassembly, if you're interested.

Go相关问答推荐

为什么工具链指令在这种情况下没有效果?

为什么没有正确生成这些元组?

如果values.yaml文件中不存在某个属性,如何返回默认的FALSE?

golang regex基于关键字拆分字符串

通过 Terraform 中的 MapNestedAtribute 进行迭代

Go test "-run -" 标志执行测试更快

为什么docall在singleflight中使用go panic?

为什么 net/http 不遵守超过 30 秒的超时持续时间?

错误!在为 age-viewer-go 运行 wails dev 或 wails build 命令时

使用模拟在 golang 中测试我的界面.专门测试调用同级函数的 1 个函数

获取切片元素的地址是否意味着 Go 中元素的副本?

使用 go.work 文件在多个测试文件上运行 go test 命令

GRPC 元数据未在 Go 中更新

在 Go 中发送 ack 和 term 后消息仍在 nats 限制队列中

如何在 golang 中同时加载 .env 文件和 os 环境变量

Golang泛型在用作 map 元素时不起作用

如何使用 math/big 对 bigInt 进行取模?

如何在 GORM 中迭代一个 int 数组

如何排除溢出矩阵的坐标

如何使用 fyne 避免 GUI 应用程序中的循环依赖?