Функция runtime.FuncForPC

Функция runtime.FuncForPC возвращает объект типа *runtime.Func, который содержит информацию о функции, ассоциированной с переданным значением программного счетчика (PC). В качестве аргумента она принимает значение типа uintptr, представляющее адрес инструкции. Если переданный PC не соответствует ни одной известной функции, функция возвращает nil.

Синтаксис

goruntime.FuncForPC(pc uintptr) *runtime.Func

Полученный объект *runtime.Func предоставляет методы для получения имени функции, ее исходного файла и строки, а также для преобразования значений PC внутри функции.

Пример 1

Давайте получим информацию о текущей функции с помощью runtime.Caller и runtime.FuncForPC:

gopackage main

import (
  "fmt"
  "runtime"
)

func main() {
  pc, file, line, ok := runtime.Caller(0)
  if !ok {
    fmt.Println("Failed to get caller information")
    return
  }

  fn := runtime.FuncForPC(pc)
  if fn != nil {
    fmt.Printf("Function: %s\n", fn.Name())
    fmt.Printf("File: %s\n", file)
    fmt.Printf("Line: %d\n", line)
  }
}

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

go"Function: main.main"
"File: /path/to/your/file.go"
"Line: 10"

Пример 2

Получим информацию о функции, вызванной из другой функции. Для этого используем runtime.Callers для получения стека вызовов:

gopackage main

import (
  "fmt"
  "runtime"
)

func outer() {
  inner()
}

func inner() {
  pc := make([]uintptr, 10)
  n := runtime.Callers(1, pc)
  if n == 0 {
    fmt.Println("No callers found")
    return
  }

  for i := 0; i < n; i++ {
    fn := runtime.FuncForPC(pc[i])
    if fn != nil {
      fmt.Printf("Caller %d: %s\n", i, fn.Name())
    }
  }
}

func main() {
  outer()
}

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

go"Caller 0: main.inner"
"Caller 1: main.outer"
"Caller 2: main.main"

Пример 3

Используем метод runtime.Func.Entry для получения начального адреса функции и метод runtime.Func.FileLine для получения файла и строки по конкретному значению PC:

gopackage main

import (
  "fmt"
  "runtime"
)

func testFunc() {
  fmt.Println("Inside testFunc")
}

func main() {
  pc, _, _, _ := runtime.Caller(0)
  fn := runtime.FuncForPC(pc)

  if fn != nil {
    fmt.Printf("Entry point: %x\n", fn.Entry())
  }

  testFn := runtime.FuncForPC(runtime.FuncForPC(pc).Entry())
  if testFn != nil {
    file, line := testFn.FileLine(pc)
    fmt.Printf("FileLine: %s:%d\n", file, line)
  }
}

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

go"Entry point: 106b6c0"
"FileLine: /path/to/your/file.go:15"

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

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