内容简介:之前也有方括号里的select表示阻塞原因,具体定义见后面的时间是阻塞时间。需要注意的是这只是一个大概时间,是在
之前也有 文章 讲过 go 调用堆栈的话题,但并没有完全讲清楚,这里补充里面缺漏的几个点。
阻塞
goroutine 1 [select, 2 minutes]:
方括号里的select表示阻塞原因,具体定义见 runtime.waitReason 。
后面的时间是阻塞时间。需要注意的是这只是一个大概时间,是在 gc的过程中标记的 ,所以如果这个goroutine不需要gc,那么永远也不会有值。
PC偏移
github.com/robfig/cron.(*Cron).run(0xc0000c44b0)
cron.go:191 +0x28d
行号后面的16进制数是什么?pc偏移。是指函数入口(cron.(*Cron).run)到调用处(也就是行号指位置)的指令位置偏差。一般很少用到,除非下面这种特殊情况:
func main() {
rand.Seed(time.Now().UnixNano())
_, _, _ = foo(), foo(), foo()
}
func foo() int {
if rand.NormFloat64() > 0 {
panic("")
}
return 0
}
//main.main()
// main.go:10 +0x7b 或 +0x80 或 +0x85
函数参数
函数参数是最复杂的部分,牵涉到go的很多底层实现。
输入参数,输出参数
为什么经常只有一个参数的函数堆栈里却跟着两个数呢?另一个是输出。
func main() {
rand.Seed(time.Now().UnixNano())
r := rand.Int() //2e78e7b163438cc2
fmt.Printf("%x\n", r)
foo(r)
}
func foo(i int) (o int) {
o = rand.Int() //36dd26e720cac1fe
fmt.Printf("%x\n", o)
defer panic("want to panic")
return
}
//main.foo(2e78e7b163438cc2, 36dd26e720cac1fe)
// main.go:21 +0xdd
结构体展开
结构体会被展开,然后比较短的字段会被打包成一个uint。
type S struct {
a int
b int
c int
d int
a1 bool
b1 byte
c1 bool
d1 byte
}
func main() {
foo(S{})
}
func foo(s S) {
panic("want to panic")
noInline()
}
func noInline() {
fmt.Sprint()
}
//main.foo(0x0, 0x0, 0x0, 0x0, 0x0)
// main.go:67 +0x39
但是这种打包是依赖字段顺序的。
type S struct {
a int
a1 bool
b int
b1 bool
c int
c1 bool
d int
d1 bool
}
func main() {
foo(S{})
}
func foo(s S) {
panic("want to panic")
noInline()
}
func noInline() {
fmt.Sprint()
}
//main.foo(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
// main.go:67 +0x39
函数参数对照表
下面的表涵盖了大部分情况
| 函数签名 | 输入 | 堆栈输出 | 说明 |
|---|---|---|---|
| foo(float64) | 1 | (0x3ff0000000000000) | |
| foo(complex64) | 1+3i | (0x404000003f800000) | 两个32位浮点打包为一个64位数 |
| foo(complex128) | 1+3i | (0x3ff0000000000000, 0x4008000000000000) | |
| foo(string) | "中文" | (0x10adc82, 0x6) | (指针,字节数) |
| foo(interface{}) | "" | (0x108e520, 0x10bff30) | (类型指针,值指针) |
| foo(interface{}) | (*string)(nil) | (0x108b8e0, 0x0) | 值为nil,类型不为nil |
| foo(interface{}) | nil | (0x0, 0x0) | 值,类型都为nil |
| foo([]byte) | make([]byte,3,6) | (0xc000070f82, 0x3, 0x6) | (指针,len,cap) |
| foo(map[string]string) | make(map[string]string) | (0xc000070e48) | |
| foo(chan struct{}) | make(chan struct{}) | (0xc00005e060) | |
| foo([200]int) | [200]int{} | (0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...) | 数组展开 |
| foo(func()) | nil | (0x0) | |
| foo(int16, uint16) | 1,2 | (0xc000020001) | 两个16位数打包为32位数,仅低32位有效 |
| foo(bool)bool | false | (0xc000070f00, 0xc00005c058) | 前一个数为输入,仅低8位有效,后一个数为输出,未初始化 |
| foo(struct {a,b int}) | struct {a,b int}{} | (0x0, 0x0) | 结构体展开 |
| foo(struct {a int;b bool;c int;d bool;e byte}) | struct {a int;b bool;c byte;d bool;e byte}{1,true,2,false,3} | (0x1, 0x1, 0x2, 0x300) | d,e合并,b不合并 |
| foo(struct {a int;b bool;c string;d bool;e byte}) | struct {a int;b bool;c string;d bool;e byte}{1,true,"a",false,3} | (0x1, 0x1, 0x10adb18, 0x1, 0x300) | d,e合并 |
| foo(struct {a struct{a,b byte};b bool}) | struct {a struct{a,b byte};b bool}{struct{a,b byte}{3,4},true} | (0xc000010403) | 内嵌结构体合并 |
| foo(struct {a struct{a int;b byte};b bool}) | struct {a struct{a int;b byte};b bool}{struct {a int;b byte}{5 , 7 },false} | (0x5, 0xc000072f07, 0xc00005e000) | 内嵌结构体不合并 |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 调用堆栈
- 前端进阶(第一期)-调用堆栈笔记
- GDB入门教程之查看函数调用堆栈
- JavaScript的工作原理:引擎,运行时和调用堆栈
- 【译】JavaScript的工作原理:引擎,运行时和调用堆栈的概述
- 用于在高性能计算应用中检测异常调用堆栈树的可视分析框架 (A Visual Analytics Framework for th...
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python编程无师自通
[美] 科里·奥尔索夫(Cory Althoff) / 宋秉金 / 人民邮电出版社 / 2019-1-1 / 59
畅销Python编程类入门书,美国亚马逊Kindle编程类排行榜榜一。 作者从文科毕业,通过自学编程转行为专业程序员,在硅谷工作多年后成功技术创业。本书不仅教读者如何使用Python语言编程,还会介绍其他书中所忽略的、编程初学者应该了解并掌握的其他所有知识点。 本书作者是一名自学成才的程序员,经过一年的自学,掌握了编程技能并在eBay找到了一份软件工程师的工作。本书是作者结合个人经验写......一起来看看 《Python编程无师自通》 这本书的介绍吧!
RGB转16进制工具
RGB HEX 互转工具
RGB CMYK 转换工具
RGB CMYK 互转工具