我试图理解go的内部结构,请看下面的代码
a,b := 10,5 b,a = a,b
上面的代码完美地交换了2个数字,a变成了5,b变成了10。我不明白这是怎么工作的。考虑到在代码的第二行,如果a先赋给b,那么b就会是10。现在如果我们把b赋给a,那么a不应该也是10。请帮助我了解这是如何工作的谢谢
7xzttuei1#
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,然后按CTRL - F键输入myfunction(这是该名称的意义所在:很容易搜索),然后找到了这四行代码,它们对应于Go语言中myfunction的前两行:(注意这是针对我的64位机器的;在其他架构(如32位)上输出会有所不同)
go tool compile -S > swap.s
myfunction
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看看the Golang docs on asm,我们可以看到汇编程序使用间接寻址来改变值。当程序运行时,CPU足够聪明,可以看到发生了什么,并使用寄存器来避免覆盖现有的值。Here's the full disassembly, if you're interested.
nx7onnlm2#
值得注意的是,在Go语言中,当我们使用a,B=b,a时,Go语言运行时会使用按位操作来执行内部交换。当交换两个变量时,Go语言运行时会在内部使用按位异或操作来交换值。它比使用临时变量来存储其中一个值的传统方法要快。
4smxwvx53#
下面是我在Go语言中交换数字的实现:
func swap_int(a *int, b *int) { var x int x = *a *a = *b *b = x } func main() { var a int = 40 var b int = 32 fmt.Println("a = %d, b = %d\n", a, b) swap_int(&a, &b) fmt.Println("a = %d, b = %d", a, b) }
3条答案
按热度按时间7xzttuei1#
TL;DR:反汇编表明CPU必须足够聪明,能够看到发生了什么,并使用寄存器来避免覆盖内存中的现有值。
这个问题让我对Golang有了更多的了解,谢谢!
要弄清楚编译器是如何生成本机代码的,我们需要查看它生成的汇编代码,链接器将其转换为机器码。
我写了一个小的围棋程序来帮助解决这个问题:
使用
go tool compile -S > swap.s
,然后按CTRL - F键输入myfunction
(这是该名称的意义所在:很容易搜索),然后找到了这四行代码,它们对应于Go语言中myfunction
的前两行:(注意这是针对我的64位机器的;在其他架构(如32位)上输出会有所不同)Go语言的反汇编对调试很有帮助:D
看看the Golang docs on asm,我们可以看到汇编程序使用间接寻址来改变值。
当程序运行时,CPU足够聪明,可以看到发生了什么,并使用寄存器来避免覆盖现有的值。
Here's the full disassembly, if you're interested.
nx7onnlm2#
值得注意的是,在Go语言中,当我们使用a,B=b,a时,Go语言运行时会使用按位操作来执行内部交换。
当交换两个变量时,Go语言运行时会在内部使用按位异或操作来交换值。
它比使用临时变量来存储其中一个值的传统方法要快。
4smxwvx53#
下面是我在Go语言中交换数字的实现: