From 565807566e08907d8b37569c8d044c0ef220b45b Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 19 Apr 2017 15:39:04 -0700 Subject: [PATCH] runtime: improve ExampleFrames CL 40876 changed ExampleFrames so that the output was stable with and without mid-stack inlining. However, that change lost some of the pedagogical and copy/paste value of the example. It was unclear why both more and i were being tracked, and whether the 5 in i < 5 is related to len(pc), and if so, why and how. This CL rewrites the example with lots more comments, and such that the core structure more closely matches normal usage, and such that it is obvious which lines of code should be deleted when copying. As a bonus, it also now illustrates Frame.File. Change-Id: Iab73541dd096657ddf79c5795337e8b596d89740 Reviewed-on: https://go-review.googlesource.com/41136 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: Austin Clements --- src/runtime/example_test.go | 38 ++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/runtime/example_test.go b/src/runtime/example_test.go index 69619b1087..e4912a5158 100644 --- a/src/runtime/example_test.go +++ b/src/runtime/example_test.go @@ -7,21 +7,37 @@ package runtime_test import ( "fmt" "runtime" + "strings" ) func ExampleFrames() { c := func() { - pc := make([]uintptr, 5) + // Ask runtime.Callers for up to 10 pcs, including runtime.Callers itself. + pc := make([]uintptr, 10) n := runtime.Callers(0, pc) if n == 0 { + // No pcs available. Stop now. + // This can happen if the first argument to runtime.Callers is large. return } - frames := runtime.CallersFrames(pc[:n]) - var frame runtime.Frame - for i, more := 0, true; more && i < 5; i++ { - frame, more = frames.Next() - fmt.Printf("- %s\n", frame.Function) + pc = pc[:n] // pass only valid pcs to runtime.CallersFrames + frames := runtime.CallersFrames(pc) + + // Loop to get frames. + // A fixed number of pcs can expand to an indefinite number of Frames. + for { + frame, more := frames.Next() + // To keep this example's output stable + // even if there are changes in the testing package, + // stop unwinding when we leave package runtime. + if !strings.Contains(frame.File, "runtime/") { + break + } + fmt.Printf("- more:%v | %s\n", more, frame.Function) + if !more { + break + } } } @@ -30,9 +46,9 @@ func ExampleFrames() { a() // Output: - // - runtime.Callers - // - runtime_test.ExampleFrames.func1 - // - runtime_test.ExampleFrames.func2 - // - runtime_test.ExampleFrames.func3 - // - runtime_test.ExampleFrames + // - more:true | runtime.Callers + // - more:true | runtime_test.ExampleFrames.func1 + // - more:true | runtime_test.ExampleFrames.func2 + // - more:true | runtime_test.ExampleFrames.func3 + // - more:true | runtime_test.ExampleFrames }