原文章中的6l和6g在go tool里面没有找到,查了网上的相关资料有了以下的补充: 使用的工具是go tool compile 和 go tool objdump
go tool
复制代码
这里我标注出了两个最常用的工具 go tool compile 和 go tool objdump。在我们卷 Go 汇编底层的时候,业内还有这么一句黑话:
几乎没有任何一个 Go 汇编底层问题不是用一条 go tool compile 不能解决的,如果不行的话,就用 go tool objdump,总能知道是怎么回事。
再让我们看看这两句指令在具体场合下都是什么意思:
go tool compile -S main.go # 反编译代码为汇编代码。
go tool objdump # 可用于查看任意函数的机器码、汇编指令、偏移。(go 源码下面有个 cmd/internal/goobj包,可以读到.o文件的重定向信息,更好)
go tool objdump -S 二进制 # Objdump 打印二进制文件中所有文本符号(代码)的反汇编。如果存在 -S 选项,objdump 只会反汇编名称与正则表达式匹配的符号。
我们来编写一个小案例进行汇编调试实践:
package main
import "fmt"
func main() {
var a = "hello"
var b = []byte(a)
fmt.Println(b)
}
复制代码
通过反汇编工具来查看一下:
go tool compile -S ./hello.go | grep "hello.go:5"
复制代码
这条命令的意思是,产生 .o 目标文件,并且把目标的汇编内容输出出来。后面跟上管道,用 grep 截取出来 hello.go 编译出来第五行的汇编代码。这里大部分汇编代码其实我们不需要看懂,我们只需要它调用了其中某个函数就知道了。
对于初学者来说,学习Go汇编不需要全都懂,只需要一些关键路径在干什么就行。比如这里最关键的是 "runtime.stringtoslicebyte(SB)",即我们要把 string 转换成 byte 数组,底层会调用这个函数。
掌握了这个方法我们就能解决之前文章中提到的第一个问题:
场景1,这两段代码运行速度怎样?第一个比第二个快?
// 代码1
package main
type person struct {
age int
}
func main() {
var a = &person{111}
println(a)
}
复制代码
// 对比代码2
package main
type person struct {
age int
}
func main() {
var b = person {111}
var a = &b
println(a)
}
复制代码
我们来看看第一个代码第 8 行编译后变成啥了:
再来看看第二个代码第 8 和第 9 行:
由此,我们可以得出结论:一行版本的代码和两行版本的代码最终编译出的结果是完全一致的,没有任何区别。