Функция runtime.Callers
Функция runtime.Callers заполняет переданный срез значениями программного счетчика (program counters) для вызовов в стеке текущей горутины. Первым параметром функция принимает значение skip - количество уровней стека, которые необходимо пропустить. Вторым параметром принимается срез типа []uintptr, в который будут записаны значения ПК. Функция возвращает количество записанных элементов.
Синтаксис
runtime.Callers(skip int, pc []uintptr) int
Пример
Давайте получим стек вызовов и преобразуем его в читаемый формат с помощью runtime.FuncForPC:
package main
import (
"fmt"
"runtime"
)
func main() {
pc := make([]uintptr, 10)
n := runtime.Callers(0, pc)
pc = pc[:n]
for _, p := range pc {
f := runtime.FuncForPC(p)
if f != nil {
file, line := f.FileLine(p)
fmt.Printf("%s:%d %s\n", file, line, f.Name())
}
}
}
Результат выполнения кода:
"/usr/local/go/src/runtime/proc.go:250 runtime.main"
"/usr/local/go/src/runtime/asm_amd64.s:1598 runtime.goexit"
Пример
Давайте пропустим определенное количество уровней стека с помощью параметра skip:
package main
import (
"fmt"
"runtime"
)
func outer() {
inner()
}
func inner() {
pc := make([]uintptr, 5)
n := runtime.Callers(1, pc) // Пропускаем inner
pc = pc[:n]
for _, p := range pc {
f := runtime.FuncForPC(p)
if f != nil {
fmt.Println(f.Name())
}
}
}
func main() {
outer()
}
Результат выполнения кода:
"main.outer"
"main.main"
Пример
Давайте обработаем ошибку, когда срез недостаточно велик для хранения всех ПК:
package main
import (
"fmt"
"runtime"
)
func main() {
pc := make([]uintptr, 2)
n := runtime.Callers(0, pc)
fmt.Printf("Requested: %d, Got: %d\n", len(pc), n)
}
Результат выполнения кода:
"Requested: 2, Got: 2"
Смотрите также
-
функцию
runtime.Caller,
которая возвращает информацию о вызывающем файле и строке -
функцию
runtime.FuncForPC,
которая возвращает функцию по адресу программного счетчика -
функцию
runtime.Stack,
которая возвращает форматированный стек вызовов в виде строки -
функцию
runtime.Frames,
которая предоставляет итератор по кадру стека