[英]How to get name of current package in go?
有沒有辦法在運行時獲取當前包的名稱?
package main
import "fmt"
func main() {
pkgName := {some magic here:)}
fmt.Println(pkgName)
}
...結果應該是“主要”
現在我正在使用常量,例如:
package main
import "fmt"
const (
pkgName = "main"
)
func main() {
fmt.Println(pkgName)
}
但我很好奇你是否可以避免這種情況
這是我的記錄器包的一部分。 它檢索有關日志記錄函數調用者的信息,以便稍后在輸出中顯示它。
func retrieveCallInfo() *callInfo {
pc, file, line, _ := runtime.Caller(2)
_, fileName := path.Split(file)
parts := strings.Split(runtime.FuncForPC(pc).Name(), ".")
pl := len(parts)
packageName := ""
funcName := parts[pl-1]
if parts[pl-2][0] == '(' {
funcName = parts[pl-2] + "." + funcName
packageName = strings.Join(parts[0:pl-2], ".")
} else {
packageName = strings.Join(parts[0:pl-1], ".")
}
return &callInfo{
packageName: packageName,
fileName: fileName,
funcName: funcName,
line: line,
}
}
如您所見,它也會返回包名稱。
我能找到的最接近的是:
package main
import (
"azul3d.org/lmath.v1"
"fmt"
"reflect"
)
type Empty struct{}
func main() {
fmt.Println(reflect.TypeOf(Empty{}).PkgPath())
fmt.Println(reflect.TypeOf(lmath.Vec3{0, 0, 0}).PkgPath())
}
這將輸出:
main
azul3d.org/lmath.v1
您還可以讀取文件的第一行並刪除“package”子字符串。 (不確定這是不是最好的主意)
package main
import (
"bufio"
"bytes"
"fmt"
"os"
)
func main() {
file, err := os.Open("so.go")
if err != nil {
panic(err)
}
r := bufio.NewReader(file)
line, _, err := r.ReadLine()
if err != nil {
panic(err)
}
packageName := bytes.TrimPrefix(line, []byte("package "))
fmt.Println(string(packageName))
}
要可靠地獲取包名稱,可以使用go編譯器的解析器來僅解析package子句。
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
)
func packageName(file string) (string, error) {
fset := token.NewFileSet()
// parse the go soure file, but only the package clause
astFile, err := parser.ParseFile(fset, l.path, nil, parser.PackageClauseOnly)
if err != nil {
return "", err
}
if astFile.Name == nil {
return "", fmt.Errorf("no package name found")
}
return astFile.Name.Name, nil
}
這可能有所幫助:
import (
"runtime"
"strings"
)
func Package() string {
pc, _, _, _ := runtime.Caller(1)
parts := strings.Split(runtime.FuncForPC(pc).Name(), ".")
pl := len(parts)
pkage := ""
funcName := parts[pl-1]
if parts[pl-2][0] == '(' {
funcName = parts[pl-2] + "." + funcName
pkage = strings.Join(parts[0:pl-2], ".")
} else {
pkage = strings.Join(parts[0:pl-1], ".")
}
return pkage
}
我實際上找到了一個更好的解決方案,在這里的這個函數中,你只需簡單地傳遞一個函數,輸出就會簡單而直接。
package main
import (
"reflect"
"runtime"
"strings"
)
func GetPackageName(temp interface{}) string {
strs := strings.Split((runtime.FuncForPC(reflect.ValueOf(temp).Pointer()).Name()), ".")
strs = strings.Split(strs[len(strs)-2], "/")
return strs[len(strs)-1]
}
這是您如何使用它的示例:
package main
import "fmt"
func main() {
fmt.Println(GetPackageName(main))
}
這是您應該期待的答案:
main
這是我的一個應用程序中技術含量非常低的解決方案,這將返回一個變量來自的包:
func pkgName(x interface{}) string {
varType := strings.TrimPrefix(fmt.Sprintf("%T", x), "*")
return strings.TrimSuffix(varType, path.Ext(varType))
}
要獲取當前包,請在本地聲明一個變量並將其傳入。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.