Подтвердить что ты не робот

Как получить текущее имя функции

Для целей трассировки я хотел бы напечатать текущее имя функции, например макрос __FUNCTION__ в gcc.

Итак, когда у меня есть функция

func foo () {
   trace()
}

он автоматически распечатает Entering foo()... или что-то в этом роде.

4b9b3361

Ответ 1

[Примечание: перейдите на 1. 7+ рекомендует использовать runtime.CallersFrames вместо runtime.FuncForPC; другой ответ содержит обновленный пример].

Пакет runtime - это ваш друг здесь:

func trace() {
    pc := make([]uintptr, 10)  // at least 1 entry needed
    runtime.Callers(2, pc)
    f := runtime.FuncForPC(pc[0])
    file, line := f.FileLine(pc[0])
    fmt.Printf("%s:%d %s\n", file, line, f.Name())
}

Ответ 2

В Go 1.7 добавлены некоторые функции времени выполнения для улучшения доступа к информации стекового фрейма.

Из Go 1.7 Примечания к выпуску:

Новая функция CallersFrames преобразует фрагмент ПК, полученный от Callers, в последовательность кадров, соответствующую стеку вызовов. Этот новый API следует предпочитать вместо прямого использования FuncForPC, поскольку последовательность кадров может более точно описывать стеки вызовов с помощью встроенных вызовов функций.

Улучшенный пример:

func trace2() {
    pc := make([]uintptr, 15)
    n := runtime.Callers(2, pc)
    frames := runtime.CallersFrames(pc[:n])
    frame, _ := frames.Next()
    fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}

площадка: https://play.golang.org/p/YkEN5mmbRld

Ответ 3

Здесь более простая версия, которой не нужно выделять массив.

func trace() (string, int, string) {
    pc, file, line, ok := runtime.Caller(1)
    if !ok { return "?", 0, "?" }

    fn := runtime.FuncForPC(pc)
    return file, line, fn.Name()
}