github.com/wangyougui/gf/v2@v2.6.5/debug/gdebug/gdebug_stack.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/wangyougui/gf. 6 7 package gdebug 8 9 import ( 10 "bytes" 11 "fmt" 12 "runtime" 13 ) 14 15 // PrintStack prints to standard error the stack trace returned by runtime.Stack. 16 func PrintStack(skip ...int) { 17 fmt.Print(Stack(skip...)) 18 } 19 20 // Stack returns a formatted stack trace of the goroutine that calls it. 21 // It calls runtime.Stack with a large enough buffer to capture the entire trace. 22 func Stack(skip ...int) string { 23 return StackWithFilter(nil, skip...) 24 } 25 26 // StackWithFilter returns a formatted stack trace of the goroutine that calls it. 27 // It calls runtime.Stack with a large enough buffer to capture the entire trace. 28 // 29 // The parameter `filter` is used to filter the path of the caller. 30 func StackWithFilter(filters []string, skip ...int) string { 31 return StackWithFilters(filters, skip...) 32 } 33 34 // StackWithFilters returns a formatted stack trace of the goroutine that calls it. 35 // It calls runtime.Stack with a large enough buffer to capture the entire trace. 36 // 37 // The parameter `filters` is a slice of strings, which are used to filter the path of the 38 // caller. 39 // 40 // TODO Improve the performance using debug.Stack. 41 func StackWithFilters(filters []string, skip ...int) string { 42 number := 0 43 if len(skip) > 0 { 44 number = skip[0] 45 } 46 var ( 47 name string 48 space = " " 49 index = 1 50 buffer = bytes.NewBuffer(nil) 51 ok = true 52 pc, file, line, start = callerFromIndex(filters) 53 ) 54 for i := start + number; i < maxCallerDepth; i++ { 55 if i != start { 56 pc, file, line, ok = runtime.Caller(i) 57 } 58 if ok { 59 if filterFileByFilters(file, filters) { 60 continue 61 } 62 if fn := runtime.FuncForPC(pc); fn == nil { 63 name = "unknown" 64 } else { 65 name = fn.Name() 66 } 67 if index > 9 { 68 space = " " 69 } 70 buffer.WriteString(fmt.Sprintf("%d.%s%s\n %s:%d\n", index, space, name, file, line)) 71 index++ 72 } else { 73 break 74 } 75 } 76 return buffer.String() 77 }