golang 交换两个数字

2024-04-19

我正在尝试了解 Go 的内部结构。考虑下面的代码

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

上面的代码完美地交换了 2 个数字,a 变成了 5,b 变成了 10。我无法理解这是如何工作的。考虑到第二行代码,如果a先分配给b,那么b将是10。现在,如果我们将b分配给a,那么a也不应该是10。

请帮助我理解这是如何工作的

Thanks


TL;DR:反汇编表明CPU必须足够聪明才能看到发生了什么并使用寄存器来避免覆盖内存中的现有值。


这个问题帮助我更多地了解了Golang,所以谢谢!

为了弄清楚编译器如何生成本机代码,我们需要查看它生成的汇编代码,该汇编代码由链接器转换为机器代码。

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

package main

import "fmt"

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

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

Using go tool compile -S > swap.s, I then CTRL - F'd for myfunction (which was the point of that name: easily searchable), and found these four lines, which correspond to the first two lines of myfunction in the Go code: (note this is for my 64-bit machine; the output will differ on other architechtures like 32-bit)

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 

Go 的反汇编对调试非常有帮助:D

看着关于 asm 的 Golang 文档 https://golang.org/doc/asm,我们可以看到汇编器使用间接来处理这些值。

当程序运行时,CPU 足够聪明,可以看到发生了什么,并使用寄存器来避免覆盖现有值。

这是完整的拆解,如果您有兴趣的话。 http://pastebin.com/3pH8Bjt7

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

golang 交换两个数字 的相关文章

  • Go 中通过 new(Type) 和 &Type{} 分配内存的区别

    考虑以下示例 type House struct func main house1 new House house2 House fmt Printf T T n house1 house2 Output main House main H
  • 在 C 中使用 Go 切片

    我正在尝试构建一个带有返回切片的函数的 go 共享库 如何使用 C 代码中的切片 package main import C type T struct A C int B C char export Test func Test T ar
  • 如何处理未知变量或如何处理多个数据库

    我正在开发一个带有多个数据库的 Go RESTful API 应用程序 启动服务器时 用户提供他们想要使用的数据库 在应用程序中 我有三大功能其中一个处理连接 selectedDb Get selectedDb Add selectedDb
  • protoc-gen-go:无法确定“simple.proto”的 Go 导入路径

    我有包含以下内容的简单原型文件 syntax proto3 package main message Person string name 1 int32 age 2 我正在尝试使用 protoc 为其生成 go 代码 我跑 protoc
  • 无法导入...(没有所需的模块提供包)

    我正在关注本教程 https www martin helmich de en blog kubernetes crd client html 我初始化我的项目并通过以下方式获取依赖项 go mod init github com mart
  • net.TCPConn 允许在 FIN 数据包后写入

    我正在尝试为一些服务器端代码编写单元测试 但我在确定关闭测试用例时遇到了困难 环回 TCP 连接似乎无法正确处理干净关闭 我在一个示例应用程序中重现了这一点 该应用程序按顺序执行以下操作 创建客户端和服务器连接 通过从客户端向服务器成功发送
  • RuntimeError:使用 docker 关闭连接后无法重用套接字

    我正在关注本教程 https github com getamis eth indexer blob master README md fbclid IwAR3g3SAjJ9ik hHCFkol2k8YXo0GvBL15oSNC hIU38
  • 记录到 golang 中的文件

    我从 golang 开始 当我开始构建我的应用程序时 我想从一开始就添加日志记录 这就是我遇到问题的地方 如果我打开一个文件并使用标准日志记录库 我就可以写入文件 就像这样 package main import os fmt log fu
  • 从私钥中提取公钥

    我尝试通过以下方式以编程方式完成步骤 2 1 openssl genrsa out signing pem 2048 2 openssl rsa in signing pem outform PEM pubout out signing p
  • 在 docker build 中缓存“go get”

    我想将 golang 单元测试封装在 docker compose 脚本中 因为它依赖于多个外部服务 我的应用程序有很多依赖项 因此需要一段时间go get 如何以允许构建 docker 容器的方式缓存包 而无需每次要测试时下载所有依赖项
  • 重写 ResponseWriter 接口以捕获 HTTP 错误

    我正在用 Go 编写一个 Web 应用程序 虽然各种 mux 库提供了一种设置自定义 404 错误处理程序的方法 但没有任何其他 4xx 和 5xx 错误代码 一个建议是重写 ResponseWriter 接口中的 WriteHeader
  • Go1编译器如何工作?

    我在一个学校项目中接触 Go 大约一个月了 我注意到 src pkg go 文件夹中的 go ast go token go parser 等包 但是 gc 编译器基于位于 src cmd gc 中的 C 文件 我的问题是关于 Go1 中用
  • Go 中的格式错误 - %s %v 或 %w

    s v and w可用于格式化 Go 中的错误 将它们转换为字符串 fmt Errorf 它们在 Go 自己的工具中的使用方式似乎有所不同 In cmd go internal get path go https github com go
  • 在 Golang Server 中接受持久的 tcp 连接

    我正在尝试使用 Go 并且想创建一个 TCP 服务器 我可以通过 telnet 访问该服务器 发送命令并接收响应 const CONN HOST localhost CONN PORT 3333 CONN TYPE tcp func mai
  • 从头开始使用映像部署无法启动

    我正在使用以下内容构建图像Dockerfile FROM golang 1 19 2 bullseye as builder COPY src src WORKDIR src RUN CGO ENABLED 1 go build race
  • 如何更改“go build”的库路径

    我正在尝试与 goncurses 一起工作 在 Centos 6 上 ncurses 库很旧 5 7 想要 5 9 所以我从源代码构建了 ncurses 并将其安装到 usr lib usr include 等中 如何告诉 go get 针
  • IntelliJ 2017.1.2 GOLANG 调试不适用于包中的断点

    我的应用程序由一个 main go 文件和一些包组成 当在 main go 中命中断点时 IntelliJ 按预期工作 显示变量值等 但是 当在不同的包中设置断点时 除了被命中之外 不会显示任何变量 并且不会跳过 进入功能按预期工作 被击中
  • 读取一个文本文件,替换其中的单词,输出到另一个文本文件

    所以我试图在 GO 中编写一个程序来获取一个充满代码的文本文件并将其转换为 GO 代码 然后将该文件保存到 GO 文件或文本文件中 我一直在试图弄清楚如何保存对文本文件所做的更改 但我可以看到更改的唯一方法是通过 println 语句 因为
  • Go中funcappend的实现在哪里?

    我对 go 非常感兴趣 并尝试阅读 go 函数的实现 我发现其中一些函数没有实现 如追加或调用 The append built in function appends elements to the end of a slice If i
  • 通过 API Gateway 使用表单数据将图像发布到 Lambda 函数会导致文件无效

    I ve a 用 Go 编写的 Lambda 函数 https github com mhausenblas imgn blob master functions app uploadimg main go应该允许图像文件上传 通过 HTM

随机推荐