Josh Bleecher Snyder | 8da91a6 | 2017-02-11 14:56:16 -0800 | [diff] [blame] | 1 | // Copyright 2017 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | package runtime_test |
| 6 | |
| 7 | import ( |
| 8 | "fmt" |
| 9 | "runtime" |
Josh Bleecher Snyder | 5658075 | 2017-04-19 15:39:04 -0700 | [diff] [blame] | 10 | "strings" |
Josh Bleecher Snyder | 8da91a6 | 2017-02-11 14:56:16 -0800 | [diff] [blame] | 11 | ) |
| 12 | |
| 13 | func ExampleFrames() { |
| 14 | c := func() { |
Matthew Dempsky | 9401172 | 2021-06-17 22:12:24 -0700 | [diff] [blame] | 15 | // Ask runtime.Callers for up to 10 PCs, including runtime.Callers itself. |
Josh Bleecher Snyder | 5658075 | 2017-04-19 15:39:04 -0700 | [diff] [blame] | 16 | pc := make([]uintptr, 10) |
Josh Bleecher Snyder | 8da91a6 | 2017-02-11 14:56:16 -0800 | [diff] [blame] | 17 | n := runtime.Callers(0, pc) |
| 18 | if n == 0 { |
Matthew Dempsky | 9401172 | 2021-06-17 22:12:24 -0700 | [diff] [blame] | 19 | // No PCs available. This can happen if the first argument to |
| 20 | // runtime.Callers is large. |
| 21 | // |
| 22 | // Return now to avoid processing the zero Frame that would |
| 23 | // otherwise be returned by frames.Next below. |
Josh Bleecher Snyder | 8da91a6 | 2017-02-11 14:56:16 -0800 | [diff] [blame] | 24 | return |
| 25 | } |
| 26 | |
Josh Bleecher Snyder | 5658075 | 2017-04-19 15:39:04 -0700 | [diff] [blame] | 27 | pc = pc[:n] // pass only valid pcs to runtime.CallersFrames |
| 28 | frames := runtime.CallersFrames(pc) |
| 29 | |
| 30 | // Loop to get frames. |
Matthew Dempsky | 9401172 | 2021-06-17 22:12:24 -0700 | [diff] [blame] | 31 | // A fixed number of PCs can expand to an indefinite number of Frames. |
Josh Bleecher Snyder | 5658075 | 2017-04-19 15:39:04 -0700 | [diff] [blame] | 32 | for { |
| 33 | frame, more := frames.Next() |
Matthew Dempsky | 9401172 | 2021-06-17 22:12:24 -0700 | [diff] [blame] | 34 | |
| 35 | // Process this frame. |
| 36 | // |
Josh Bleecher Snyder | 5658075 | 2017-04-19 15:39:04 -0700 | [diff] [blame] | 37 | // To keep this example's output stable |
| 38 | // even if there are changes in the testing package, |
| 39 | // stop unwinding when we leave package runtime. |
| 40 | if !strings.Contains(frame.File, "runtime/") { |
| 41 | break |
| 42 | } |
| 43 | fmt.Printf("- more:%v | %s\n", more, frame.Function) |
Matthew Dempsky | 9401172 | 2021-06-17 22:12:24 -0700 | [diff] [blame] | 44 | |
| 45 | // Check whether there are more frames to process after this one. |
Josh Bleecher Snyder | 5658075 | 2017-04-19 15:39:04 -0700 | [diff] [blame] | 46 | if !more { |
| 47 | break |
| 48 | } |
Josh Bleecher Snyder | 8da91a6 | 2017-02-11 14:56:16 -0800 | [diff] [blame] | 49 | } |
| 50 | } |
| 51 | |
| 52 | b := func() { c() } |
| 53 | a := func() { b() } |
| 54 | |
| 55 | a() |
| 56 | // Output: |
Josh Bleecher Snyder | 5658075 | 2017-04-19 15:39:04 -0700 | [diff] [blame] | 57 | // - more:true | runtime.Callers |
| 58 | // - more:true | runtime_test.ExampleFrames.func1 |
| 59 | // - more:true | runtime_test.ExampleFrames.func2 |
| 60 | // - more:true | runtime_test.ExampleFrames.func3 |
| 61 | // - more:true | runtime_test.ExampleFrames |
Josh Bleecher Snyder | 8da91a6 | 2017-02-11 14:56:16 -0800 | [diff] [blame] | 62 | } |