Функция runtime.Callers

Функция runtime.Callers заполняет переданный срез значениями программного счетчика (program counters) для вызовов в стеке текущей горутины. Первым параметром функция принимает значение skip - количество уровней стека, которые необходимо пропустить. Вторым параметром принимается срез типа []uintptr, в который будут записаны значения ПК. Функция возвращает количество записанных элементов.

Синтаксис

goruntime.Callers(skip int, pc []uintptr) int

Пример

Давайте получим стек вызовов и преобразуем его в читаемый формат с помощью runtime.FuncForPC:

gopackage 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())
    }
  }
}

Результат выполнения кода:

go"/usr/local/go/src/runtime/proc.go:250 runtime.main"
"/usr/local/go/src/runtime/asm_amd64.s:1598 runtime.goexit"

Пример

Давайте пропустим определенное количество уровней стека с помощью параметра skip:

gopackage 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()
}

Результат выполнения кода:

go"main.outer"
"main.main"

Пример

Давайте обработаем ошибку, когда срез недостаточно велик для хранения всех ПК:

gopackage 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)
}

Результат выполнения кода:

go"Requested: 2, Got: 2"

Смотрите также

  • функцию runtime.Caller,
    которая возвращает информацию о вызывающем файле и строке
  • функцию runtime.FuncForPC,
    которая возвращает функцию по адресу программного счетчика
  • функцию runtime.Stack,
    которая возвращает форматированный стек вызовов в виде строки
  • функцию runtime.Frames,
    которая предоставляет итератор по кадру стека