go语言中哪些变量放在栈 golang变量( 二 )


如果原来数组切片的容量已经达到了最大值,再想扩容 ,  Go 默认会先开一片内存区域 , 把原来的值拷贝过来,然后再执行 append() 操作 。这种情况对现数组的地址和原数组地址不相同 。
从上面结果我们可以看到,如果用 range 的方式去遍历一个切片,拿到的 Value 其实是切片里面的值拷贝,即浅拷贝 。所以每次打印 Value 的地址都不变 。
由于 Value 是值拷贝的 , 并非引用传递,所以直接改 Value 是达不到更改原切片值的目的的,需要通过 slice[index] 获取真实的地址 。
go程序如何分配堆栈的在Go语言中有一些调试技巧能帮助go语言中哪些变量放在栈我们快速找到问题go语言中哪些变量放在栈 , 有时候go语言中哪些变量放在栈你想尽可能多的记录异常但仍觉得不够,搞清楚堆栈的意义有助于定位Bug或者记录更完整的信息 。
本文将讨论堆栈跟踪信息以及如何在堆栈中识别函数所传递的参数 。
Functions
先从这段代码开始go语言中哪些变量放在栈:
Listing 1
01 package main
02
03 func main() {
04slice := make([]string, 2, 4)
05Example(slice, "hello", 10)
06 }
07
08 func Example(slice []string, str string, i int) {
09panic("Want stack trace")
10 }
Example函数定义了3个参数,1个string类型的slice, 1个string和1个integer, 并且抛出了panic,运行这段代码可以看到这样的结果go语言中哪些变量放在栈:
Listing 2
Panic: Want stack trace
goroutine 1 [running]:
main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:9 +0x64
main.main()
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:5 +0x85
goroutine 2 [runnable]:
runtime.forcegchelper()
/Users/bill/go/src/runtime/proc.go:90
runtime.goexit()
/Users/bill/go/src/runtime/asm_amd64.s:2232 +0x1
goroutine 3 [runnable]:
runtime.bgsweep()
/Users/bill/go/src/runtime/mgc0.go:82
runtime.goexit()
/Users/bill/go/src/runtime/asm_amd64.s:2232 +0x1
堆栈信息中显示了在panic抛出这个时间所有的goroutines状态 , 发生的panic的goroutine会显示在最上面 。
Listing 3
01 goroutine 1 [running]:
02 main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:9 +0x64
03 main.main()
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:5 +0x85
第1行显示最先发出panic的是goroutine 1, 第二行显示panic位于main.Example中, 并能定位到该行代码,在本例中第9行引发了panic 。
下面我们关注参数是如何传递的:
Listing 4
// Declaration
main.Example(slice []string, str string, i int)
// Call to Example by main.
slice := make([]string, 2, 4)
Example(slice, "hello", 10)
// Stack trace
main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
这里展示了在main中带参数调用Example函数时的堆栈信息,比较就能发现两者的参数数量并不相同,Example定义了3个参数,堆栈中显示了6个参数 。现在的关键问题是我们要弄清楚它们是如何匹配的 。
第1个参数是string类型的slice , 我们知道在Go语言中slice是引用类型 , 即slice变量结构会包含三个部分:指针、长度(Lengthe)、容量(Capacity)
Listing 5
// Slice parameter value
slice := make([]string, 2, 4)
// Slice header values
Pointer:0x2080c3f50
Length:0x2
Capacity: 0x4
// Declaration
main.Example(slice []string, str string, i int)