go / expert
Snippet
Structured Call Stack Unwinding and Frame Extraction During Deferred Recover
Combining deferred recover() with runtime.Callers and runtime.CallersFrames enables production panic wrappers to extract programmatic stack frame details (file paths, line numbers, function names) rather than relying on formatted stack string dumps, allowing structured error reporting.
snippet.go
go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package mainimport ("fmt""runtime")type StackFrame struct {Function stringFile stringLine int}func captureStackTrace(skip int) []StackFrame {pcs := make([]uintptr, 10)n := runtime.Callers(skip, pcs)frames := runtime.CallersFrames(pcs[:n])var result []StackFramefor {frame, more := frames.Next()result = append(result, StackFrame{Function: frame.Function,File: frame.File,Line: frame.Line,})if !more {break}}return result}func safeExecute(fn func()) (err error) {defer func() {if r := recover(); r != nil {frames := captureStackTrace(3)err = fmt.Errorf("panic recovered: %v | origin: %s:%d", r, frames[0].File, frames[0].Line)}}()fn()return nil}func main() {err := safeExecute(func() {panic("critical operational failure")})fmt.Println(err)}
Breakdown
1
n := runtime.Callers(skip, pcs)
Fills program counter execution addresses into the target slice, skipping frame overhead.
2
frames := runtime.CallersFrames(pcs[:n])
Decodes program counters into human-readable source code symbols and location structures.