1
0
mirror of https://github.com/golang/go synced 2024-11-22 19:54:39 -07:00

runtime: clarify Frames.Next documentation

I wrote code that relied on this API, but I misunderstood the original
description of the "more" result. As a consequence, my code always
stopped one frame early.

This CL expands the documentation to be more explicit and specifically
call out my confusion (i.e., that the "more" result indicates whether
the *next* Next call will return a valid Frame, and not whether this
call did).

Change-Id: If135f8f8c05425073d45377c4179e4f79e6bd6ca
Reviewed-on: https://go-review.googlesource.com/c/go/+/329389
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Matthew Dempsky 2021-06-17 22:12:24 -07:00
parent 57aaa19aae
commit 9401172166
2 changed files with 21 additions and 6 deletions

View File

@ -12,12 +12,15 @@ import (
func ExampleFrames() { func ExampleFrames() {
c := func() { c := func() {
// Ask runtime.Callers for up to 10 pcs, including runtime.Callers itself. // Ask runtime.Callers for up to 10 PCs, including runtime.Callers itself.
pc := make([]uintptr, 10) pc := make([]uintptr, 10)
n := runtime.Callers(0, pc) n := runtime.Callers(0, pc)
if n == 0 { if n == 0 {
// No pcs available. Stop now. // No PCs available. This can happen if the first argument to
// This can happen if the first argument to runtime.Callers is large. // runtime.Callers is large.
//
// Return now to avoid processing the zero Frame that would
// otherwise be returned by frames.Next below.
return return
} }
@ -25,9 +28,12 @@ func ExampleFrames() {
frames := runtime.CallersFrames(pc) frames := runtime.CallersFrames(pc)
// Loop to get frames. // Loop to get frames.
// A fixed number of pcs can expand to an indefinite number of Frames. // A fixed number of PCs can expand to an indefinite number of Frames.
for { for {
frame, more := frames.Next() frame, more := frames.Next()
// Process this frame.
//
// To keep this example's output stable // To keep this example's output stable
// even if there are changes in the testing package, // even if there are changes in the testing package,
// stop unwinding when we leave package runtime. // stop unwinding when we leave package runtime.
@ -35,6 +41,8 @@ func ExampleFrames() {
break break
} }
fmt.Printf("- more:%v | %s\n", more, frame.Function) fmt.Printf("- more:%v | %s\n", more, frame.Function)
// Check whether there are more frames to process after this one.
if !more { if !more {
break break
} }

View File

@ -68,8 +68,15 @@ func CallersFrames(callers []uintptr) *Frames {
return f return f
} }
// Next returns frame information for the next caller. // Next returns a Frame representing the next call frame in the slice
// If more is false, there are no more callers (the Frame value is valid). // of PC values. If it has already returned all call frames, Next
// returns a zero Frame.
//
// The more result indicates whether the next call to Next will return
// a valid Frame. It does not necessarily indicate whether this call
// returned one.
//
// See the Frames example for idiomatic usage.
func (ci *Frames) Next() (frame Frame, more bool) { func (ci *Frames) Next() (frame Frame, more bool) {
for len(ci.frames) < 2 { for len(ci.frames) < 2 {
// Find the next frame. // Find the next frame.