preface

When the GO code is running, it may produce panic because the code is not robust as a whole. If panic is not recovered, the whole process will exit. We often need to analyze the code through the function stack that Panic throws to find the panic location

This article will cover how the same GO code behaves in GO1.16 and go1.17. The reason for using both versions is that in 1.17, go introduced a major update. Instead of just passing arguments in memory, functions are called using registers first and memory later

code

package main

func main(a) {
	getPanic([]string{"get"."panic"}, 0x1234)}//go:noinline
func getPanic(p1 []string, p2 int) string {
	panic("paniced")
	return "panic"
}
Copy the code

NOTE: // Gonoinline adds this line to prevent simple functions from being optimized inline

Let’s take a look at go1.16

panic: paniced

goroutine 1 [running]:
main.getPanic(0xc000046758, 0x2, 0x2, 0x1234, 0xc00006a058, 0x1013201)
	/Users/holen/main.go:9 +0x39
main.main()
	/Users/holen/main.go:4 +0x7d
exit status 2
Copy the code

The first thing we know is that the bottom of each stack is where each goroutine starts, and in this case, there’s only one goroutine, which is the main routine

And then look down from the top

* /Users/holen/main.go:9 * /Users/holen/main.go:9 * /Users/holen/main.go:9 * /Users/holen/main.go:9 * /Users/holen/main.go:9

It is the input parameter and return value of the getPanic function. Some people may wonder if the parameter + return value is not three parameters, why there are six parameters

0xC000046758, 0x2, 0x2 => [] String {"get","panic"} 0x1234 => 0x1234 0xC00006A058, 0x1013201 => Returned valueCopy the code

In Golang, slice is composed of three members: slice address, length and capacity, and string is composed of two elements: string address and length

Then take a look at the performance of GO1.17

panic: paniced goroutine 1 [running]: main.getPanic({0xc000048770, 0x1004319, 0x60}, 0x0) /Users/holen/main.go:9 +0x27 main.main() /Users/holen/main.go:4 +0x65 exit Status 2 The Shell returns 1Copy the code

Comparison with GO1.16 is not hard to find

  1. There are three values{}The parcel
  2. Missing some parameters
  3. The values displayed do not seem to match the parameters

Indeed, go has been optimized in 1.17 for the display of stack information. Instead of laying out all the information, go will use {} groups to indicate that these are three elements of one parameter. Secondly, there are fewer return value parameters, which is actually the same problem with question 3. It is all caused by the change of the parameter transfer convention in the function call of go in 1.17. Therefore, these parameters are actually in the register, so the display is not correct