code1:
package main
import (
"fmt"
"github.com/pkg/errors"
"runtime"
)
func main() {
ptrs, _ := Test1("arg1", "arg2")
for _, pc := range *ptrs {
f := runtime.FuncForPC(pc)
if f == nil {
continue
}
filename, line := f.FileLine(pc)
fmt.Printf("func name: %s, entry: %x, filename: %s, line: %d\n", f.Name(), f.Entry(), filename, line)
}
}
func Test0(args ...interface{}) *[]uintptr {
const depth = 32
var pcs [depth]uintptr
n := runtime.Callers(0, pcs[:])
st := pcs[0:n]
return &st
}
func Test1(args ...interface{}) (*[]uintptr, error) {
return Test0(args...), errors.New("Test")
}
code2:
package main
import (
"fmt"
"runtime"
)
func main() {
ptrs, _ := Test1("arg1", "arg2")
for _, pc := range *ptrs {
f := runtime.FuncForPC(pc)
if f == nil {
continue
}
filename, line := f.FileLine(pc)
fmt.Printf("func name: %s, entry: %x, filename: %s, line: %d\n", f.Name(), f.Entry(), filename, line)
}
}
func Test0(args ...interface{}) *[]uintptr {
const depth = 32
var pcs [depth]uintptr
n := runtime.Callers(0, pcs[:])
st := pcs[0:n]
return &st
}
func Test1(args ...interface{}) (*[]uintptr, error) {
return Test0(args...), nil//, errors.New("Test")
}
The only different part is returning error value of Test1()
. In the code1 it returns erors.New("Test")
, in the code2 it returns nil
. In the FOR loop of main
function, the program prints function name, the results are different:
result of code1:
func name: runtime.Callers, entry: 6a20c0, filename: C:/Program Files/Go/src/runtime/extern.go, line: 247
func name: runtime.Callers, entry: 6a20c0, filename: C:/Program Files/Go/src/runtime/extern.go, line: 247
func name: main.Test1, entry: 6a2180, filename: D:/develop/go-testbed/cmd/slicetest/slicetest.go, line: 30
func name: main.main, entry: 6a1ea0, filename: D:/develop/go-testbed/cmd/slicetest/slicetest.go, line: 11
func name: runtime.main, entry: 6476a0, filename: C:/Program Files/Go/src/runtime/proc.go, line: 259
func name: runtime.goexit, entry: 66eee0, filename: C:/Program Files/Go/src/runtime/asm_amd64.s, line: 1595
result of code2
func name: runtime.Callers, entry: b30020, filename: C:/Program Files/Go/src/runtime/extern.go, line: 247
func name: runtime.Callers, entry: b30020, filename: C:/Program Files/Go/src/runtime/extern.go, line: 247
func name: main.main, entry: b2fe00, filename: D:/develop/go-testbed/cmd/slicetest/slicetest.go, line: 10
func name: main.main, entry: b2fe00, filename: D:/develop/go-testbed/cmd/slicetest/slicetest.go, line: 9
func name: runtime.main, entry: ad6fc0, filename: C:/Program Files/Go/src/runtime/proc.go, line: 259
func name: runtime.goexit, entry: afe580, filename: C:/Program Files/Go/src/runtime/asm_amd64.s, line: 1595
As you see, code1 printed the correct function name, main.Test1
but code2 didn't.
I read runtime.Callers print different program counters depending on where its run from which recommands to use runtime.CallersFrames()
but I thinks it's not the problem because both code1 and code2 do not use it. I also see the errors.New()
function but I didn't find something special. It creates callstack by caller()
function which is almost same as Test0()
in my code -- actually, I copied the contents of Test0()
from caller()
.
Can someone tell me which causes the difference?
Go version: go1.19 windows/amd64
OS: windonws 11
version of github.com/pkg/errors
: v0.9.1
Both of codes print the same result with main.Test1
if I run them in debug mode of Goland IDE.
Thank you!