反汇编相关
在线反汇编:
string
在部分内置调用上, []byte可以无损的转化为string, 而无需调用runtime.slicebytetostring
目前已知的调用有:
map
- range map 可以一边遍历一边删除
- 以上代码会被优化为
runtime.mapclear
range
源码: cmd/compile/internal/walk/range.go
range会再编译器通过插入代码的方式实现.
interface{}
interface{}
是一个结构体, 由类型和指针组成
- 如果赋值的元素是结构体(不是结构体指针), 则会进行复制结构体, 并将复制的结构体的指针赋值给
data
如下面的例子, 修改a和c都不会影响b
interface{}
包含类型和值, 当interface不是nil的时候, 存在类型不为nil, 值为nil的情况,
尤其在error返回的时候要注意, error一定要返回nil, 而不要返回某个类型的nil.
如下面的例子, 输出为 “a is nil” “b is not nil”
这个实现原理是interface{}
的判空只看类型是不是nil, 不看value, 下面的代码中, type被放在第一个参数rax, 类型被放在了第二个参数rbx
逃逸分析
reflect.ValueOf
会造成leaking param
, 可以参考一些golang的知识点中的反射部分.
defer函数修改return的值, 需要使用具名return
简单说一下这个的原理, 可以理解为函数堆栈上有一个返回值变量的空间,
当该变量匿名时, 执行return N时, 会给该变量赋值,
当defer执行后, 会将该变量再赋值给eax(eax是第一个返回值)
简单来说,这个原理可以理解为函数堆栈上有一个用于存储返回值的变量空间。
当该变量未命名时,执行return N语句时,会将该变量赋值为N。
紧接着执行defer语句后,该变量的值会被再次赋值给eax(eax是第一个返回值)。
package list模式的几个坑
经常使用 go
命令中的 ...
参数,以便能够对多个 package
执行命令。例如:
go test ./...
go build ./cmd/...
go clean ./cmd/...
go install ./cmd/...
最近因为...
参数的问题被坑了两次,由于网上对应的文档较少,我也没有时间去做更多的分析,所以仅简单的记录:
go test ./...
编译失败时提示不明显
当使用go test ./...
时,其中某个模块编译失败,进程会返回-2,编译错误信息在stderr, 如果有-v
就更不明显了, 尽量要分离stderr和stdout
go build -buildvcs=false ./cmd/...
不传递参数
go build -buildvcs=false ./cmd/...
并不会将 -buildvcs=false
参数传递给每个 package
,为了解决这个问题,我们改用以下代码:
stderr重定向问题
有一些panic
是unrecoverable
的, 例如:
在这种情况下,panic
产生的错误信息输出到 stderr
中。
原本计划使用 os.Stderr = file
将 stderr
重定向到文件中,但发现 print
函数(panic
输出错误信息的函数)会绕过 Golang 的 os.Stderr
,因此需要使用 syscall.Dup2(int(file.Fd()),int(os.stderr.Fd()))
来实现 stderr
的重定向,或在父进程中处理错误输出。
参数和返回值
Go internal ABI specification
golang 函数之间的调用传递参数和结果是通过使用 stack 和 registers 的联合方式。
amd64 架构使用以下 9 个寄存器序列来存储整数参数和结果: RAX, RBX, RCX, RDI, RSI, R8, R9, R10, R11
slice, string, interface{} 传参
slice 会用三个寄存器传递
string 会用两个寄存器传递
interface{} 会用两个寄存器传递(第一个是type, 第二个是value指针)
本文链接, 未经许可,禁止转载