I am attempting to create named loggers automatically for HTTP handlers that I'm writing, where I am passed a function (pointer).
I'm using the code mentioned in this question to get the name of a function:
package utils
import (
"reflect"
"runtime"
)
func GetFunctionName(fn interface{}) string {
value := reflect.ValueOf(fn)
ptr := value.Pointer()
ffp := runtime.FuncForPC(ptr)
return ffp.Name()
}
I'm using this in my main
function to try it out like so:
package main
import (
"github.com/naftulikay/golang-webapp/experiments/functionname/long"
"github.com/naftulikay/golang-webapp/experiments/functionname/long/nested/path"
"github.com/naftulikay/golang-webapp/experiments/functionname/utils"
"log"
)
type Empty struct{}
func main() {
a := long.HandlerA
b := path.HandlerB
c := path.HandlerC
log.Printf("long.HandlerA: %s", utils.GetFunctionName(a))
log.Printf("long.nested.path.HandlerB: %s", utils.GetFunctionName(b))
log.Printf("long.nested.path.HandlerC: %s", utils.GetFunctionName(c))
}
I see output like this:
github.com/naftulikay/golang-webapp/experiments/functionname/long.HandlerA
This is okay but I'd like an output such as long.HandlerA
, long.nested.path.HandlerB
, etc.
If I could get the Go module name (github.com/naftulikay/golang-webapp/experiments/functionname
), I can then use strings.Replace
to remove the module name to arrive at long/nested/path.HandlerB
, then strings.Replace
to replace /
with .
to finally get to my desired value, which is long.nested.path.HandlerB
.
The first question is: can I do better than runtime.FuncForPC(reflect.ValueOf(fn).Pointer())
for getting the qualified path to a function?
If the answer is no, is there a way to get the current Go module name using runtime
or reflect
so that I can transform the output of runtime.FuncForPC
into what I need?
Once again, I'm getting values like:
github.com/naftulikay/golang-webapp/experiments/functionname/long.HandlerA
github.com/naftulikay/golang-webapp/experiments/functionname/long/nested/path.HandlerB
github.com/naftulikay/golang-webapp/experiments/functionname/long/nested/path.HandlerC
And I'd like to get values like:
long.HandlerA
long.nested.path.HandlerB
long.nested.path.HandlerC
EDIT: It appears that Go does not have a runtime representation of modules, and that's okay, if I can do it at compile time that would be fine too. I've seen the codegen documentation and I'm having a hard time figuring out how to write my own custom codegen that can be used from go generate
.
go.mod
and embed the result in my program? – Angelesapp.routes.login.LoginHandler
. Slashes seem to work but the mix of slashes and dots seems confusing to me. I don't need a file name or a line, just need to extract that value from a function pointer. – Angelesdebug.ReadBuildInfo()
? – Raynold