Go. Узнать имя файла функции по указателю на функцию
Возможно ли в Go узнать имя файла в котором определена функция по указателю на эту функцию? Знаю, что есть runtime.Caller для получения информации по вызываемым функциям... но если мы ничего не вызываем - просто есть слайс с указателями на функции. И хочется узнать имена их файлов, так как имена самих функций New и не обладают нужной информативностью.
Объясню для чего: В коде используются множество midlleware, например: "github.com/gofiber/fiber/v2/middleware/csrf"
Middleware вызывается как csrf.New() и имея указатель на этот обработчик (в слайсе Handlers для каждого конкретного Route) я могу узнать только имя самой функции. Но это имя не говорит о том какой именно обработчик используется для этого маршрута. Тогда как имя файла вполне специфично. Вот его то и хотелось бы как-то достать...
Ответы (1 шт):
Не имя исходного файла, но имя пакета + имя функции я получил. (код funcAddr был честно украден с хабра :-))
package main
import (
"fmt"
"unsafe"
"runtime"
"reflect"
)
// funcAddr returns function value fn executable code address.
func funcAddr(fn interface{}) uintptr {
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
typ uintptr
value *uintptr
}
e := (*emptyInterface)(unsafe.Pointer(&fn))
return *e.value
}
func Func(fn interface{}) *runtime.Func {
return runtime.FuncForPC(funcAddr(fn))
}
// а так будет попроще
func funcAddr2(fn interface{}) uintptr {
return reflect.ValueOf(fn).Pointer()
}
func Func2(fn interface{}) *runtime.Func {
return runtime.FuncForPC(funcAddr2(fn))
}
func main() {
fn := runtime.FuncForPC
fmt.Printf("%T\n", fn)
fmt.Println(Func(fn).Name()) // runtime.FuncForPC
}
Дальше уже можно сделать split для разделения на имя модуля и имя файла. В случае модулей с гитхаба имя модуля придется укорачивать до последнего сегмента.