go - 在 Go 中获取当前模块的名称
问题描述
我正在尝试为我正在编写的 HTTP 处理程序自动创建命名记录器,并在其中传递了一个函数(指针)。
我正在使用这个问题中提到的代码来获取函数的名称:
package utils
import (
"reflect"
"runtime"
)
func GetFunctionName(fn interface{}) string {
value := reflect.ValueOf(fn)
ptr := value.Pointer()
ffp := runtime.FuncForPC(ptr)
return ffp.Name()
}
我在我的main
函数中使用它来尝试它:
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))
}
我看到这样的输出:
github.com/naftulikay/golang-webapp/experiments/functionname/long.HandlerA
这没关系,但我想要一个输出,例如long.HandlerA
,long.nested.path.HandlerB
等。
如果我能得到 Go 模块名称 ( github.com/naftulikay/golang-webapp/experiments/functionname
),然后我可以使用strings.Replace
删除模块名称到达long/nested/path.HandlerB
,然后strings.Replace
替换/
为.
最终得到我想要的值,即long.nested.path.HandlerB
.
runtime.FuncForPC(reflect.ValueOf(fn).Pointer())
第一个问题是:我能比获得函数的合格路径做得更好吗?
如果答案是否定的,有没有办法使用runtime
or获取当前的 Go 模块名称,reflect
以便我可以将输出runtime.FuncForPC
转换为我需要的?
再一次,我得到如下值:
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
我想获得如下值:
long.HandlerA
long.nested.path.HandlerB
long.nested.path.HandlerC
编辑: Go 似乎没有模块的运行时表示,这没关系,如果我可以在编译时这样做也可以。我已经看过 codegen 文档,我很难弄清楚如何编写我自己的自定义 codegen 可以从go generate
.
解决方案
模块信息包含在可执行二进制文件中,可以使用debug.ReadBuildInfo()
函数获取(唯一的要求是必须使用模块支持构建可执行文件,但这是当前版本的默认设置,并且可能在未来版本中唯一) .
BuildInfo.Path
是当前模块的路径。
假设您有以下go.mod
文件:
module example.com/foo
读取构建信息的示例:
bi, ok := debug.ReadBuildInfo()
if !ok {
log.Printf("Failed to read build info")
return
}
fmt.Println(bi.Path)
这将输出(在Go Playground上尝试):
example.com/foo
请参阅相关:Golang - 如何从代码内部显示模块版本
推荐阅读
- android - 是否可以使用自定义可绘制资源将工厂改回?
- java - Swagger (OpenAPI):如何指定从自定义对象动态生成的示例字符串?
- sql-server - 两个 dacpac 文件之间的详细差异
- latex - siunitx 列中的空白
- android - 在 Windows for Android 上从源代码构建 Qt5.13.2 时出错
- pandas - 迭代列表以创建数据框输出 Pandas
- python - PyPDF2 PdfFileMerger.Merge 类
- javascript - 如何从异步函数返回多个值以在另一个函数中使用
- excel - 将条目添加到表 - 添加到现有条目
- java - 多个按钮的 1 个事件