如何在Go中获取当前包的名称?

huangapple go评论129阅读模式
英文:

How to get name of current package in go?

问题

在运行时获取当前包的名称有没有办法?

  1. package main
  2. import "fmt"
  3. func main() {
  4. pkgName := {在这里加入一些魔法}
  5. fmt.Println(pkgName)
  6. }

...结果应该是"main"

目前我使用常量来实现:

  1. package main
  2. import "fmt"
  3. const (
  4. pkgName = "main"
  5. )
  6. func main() {
  7. fmt.Println(pkgName)
  8. }

但我想知道是否可以避免这样做。

英文:

Is there a way to get on runtime the name of current package?

  1. package main
  2. import "fmt"
  3. func main() {
  4. pkgName := {some magic here:)}
  5. fmt.Println(pkgName)
  6. }

... and the result should be "main"

Right now I'm using constant like:

  1. package main
  2. import "fmt"
  3. const (
  4. pkgName = "main"
  5. )
  6. func main() {
  7. fmt.Println(pkgName)
  8. }

but I'm curious if you can avoid this

答案1

得分: 39

没有 runtimereflect 的方法或函数提供您所寻找的功能。

我找到的最接近的是:

  1. package main
  2. import (
  3. "azul3d.org/lmath.v1"
  4. "fmt"
  5. "reflect"
  6. )
  7. type Empty struct{}
  8. func main() {
  9. fmt.Println(reflect.TypeOf(Empty{}).PkgPath())
  10. fmt.Println(reflect.TypeOf(lmath.Vec3{0, 0, 0}).PkgPath())
  11. }

这将输出:

  1. main
  2. azul3d.org/lmath.v1

您还可以读取文件的第一行并删除 "package" 子字符串。(不确定是否是最好的主意)

  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "fmt"
  6. "os"
  7. )
  8. func main() {
  9. file, err := os.Open("so.go")
  10. if err != nil {
  11. panic(err)
  12. }
  13. r := bufio.NewReader(file)
  14. line, _, err := r.ReadLine()
  15. if err != nil {
  16. panic(err)
  17. }
  18. packageName := bytes.TrimPrefix(line, []byte("package "))
  19. fmt.Println(string(packageName))
  20. }
英文:

There is no runtime or reflect method or function that provides the functionality that you are looking for.

The closest thing I could find is:

  1. package main
  2. import (
  3. "azul3d.org/lmath.v1"
  4. "fmt"
  5. "reflect"
  6. )
  7. type Empty struct{}
  8. func main() {
  9. fmt.Println(reflect.TypeOf(Empty{}).PkgPath())
  10. fmt.Println(reflect.TypeOf(lmath.Vec3{0, 0, 0}).PkgPath())
  11. }

This would output:

  1. main
  2. azul3d.org/lmath.v1

You could also read the first line of the file and remove the "package" substring.
(Not sure if it's the best idea)

  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "fmt"
  6. "os"
  7. )
  8. func main() {
  9. file, err := os.Open("so.go")
  10. if err != nil {
  11. panic(err)
  12. }
  13. r := bufio.NewReader(file)
  14. line, _, err := r.ReadLine()
  15. if err != nil {
  16. panic(err)
  17. }
  18. packageName := bytes.TrimPrefix(line, []byte("package "))
  19. fmt.Println(string(packageName))
  20. }

答案2

得分: 31

这是我的日志记录器包的一部分。它获取有关日志函数调用者的信息,以便稍后在输出中显示。

  1. func retrieveCallInfo() *callInfo {
  2. pc, file, line, _ := runtime.Caller(2)
  3. _, fileName := path.Split(file)
  4. parts := strings.Split(runtime.FuncForPC(pc).Name(), ".")
  5. pl := len(parts)
  6. packageName := ""
  7. funcName := parts[pl-1]
  8. if parts[pl-2][0] == '(' {
  9. funcName = parts[pl-2] + "." + funcName
  10. packageName = strings.Join(parts[0:pl-2], ".")
  11. } else {
  12. packageName = strings.Join(parts[0:pl-1], ".")
  13. }
  14. return &callInfo{
  15. packageName: packageName,
  16. fileName: fileName,
  17. funcName: funcName,
  18. line: line,
  19. }
  20. }

正如你所看到的,它还返回了包名。

英文:

Here a part of my logger package. It retrieves information about the caller of the logging function to show it later in the output.

  1. func retrieveCallInfo() *callInfo {
  2. pc, file, line, _ := runtime.Caller(2)
  3. _, fileName := path.Split(file)
  4. parts := strings.Split(runtime.FuncForPC(pc).Name(), ".")
  5. pl := len(parts)
  6. packageName := ""
  7. funcName := parts[pl-1]
  8. if parts[pl-2][0] == '(' {
  9. funcName = parts[pl-2] + "." + funcName
  10. packageName = strings.Join(parts[0:pl-2], ".")
  11. } else {
  12. packageName = strings.Join(parts[0:pl-1], ".")
  13. }
  14. return &callInfo{
  15. packageName: packageName,
  16. fileName: fileName,
  17. funcName: funcName,
  18. line: line,
  19. }
  20. }

As you can see it returns the package name too.

答案3

得分: 6

要可靠地获取包名,您可以使用Go编译器的解析器仅解析包声明部分。

  1. import (
  2. "fmt"
  3. "go/ast"
  4. "go/parser"
  5. "go/token"
  6. )
  7. func packageName(file string) (string, error) {
  8. fset := token.NewFileSet()
  9. // 解析Go源文件,但只解析包声明部分
  10. astFile, err := parser.ParseFile(fset, file, nil, parser.PackageClauseOnly)
  11. if err != nil {
  12. return "", err
  13. }
  14. if astFile.Name == nil {
  15. return "", fmt.Errorf("未找到包名")
  16. }
  17. return astFile.Name.Name, nil
  18. }

以上是获取包名的代码示例。

英文:

To reliably get the package name, you can use the go compiler's parser to parse only the package clause.

  1. import (
  2. "fmt"
  3. "go/ast"
  4. "go/parser"
  5. "go/token"
  6. )
  7. func packageName(file string) (string, error) {
  8. fset := token.NewFileSet()
  9. // parse the go soure file, but only the package clause
  10. astFile, err := parser.ParseFile(fset, l.path, nil, parser.PackageClauseOnly)
  11. if err != nil {
  12. return "", err
  13. }
  14. if astFile.Name == nil {
  15. return "", fmt.Errorf("no package name found")
  16. }
  17. return astFile.Name.Name, nil
  18. }

答案4

得分: 1

更好的解决方案

我实际上找到了一个更好的解决方案,在下面的这个函数中,你只需要传递一个函数,输出就会变得简单明了。

  1. package main
  2. import (
  3. "reflect"
  4. "runtime"
  5. "strings"
  6. )
  7. func GetPackageName(temp interface{}) string {
  8. strs := strings.Split((runtime.FuncForPC(reflect.ValueOf(temp).Pointer()).Name()), ".")
  9. strs = strings.Split(strs[len(strs)-2], "/")
  10. return strs[len(strs)-1]
  11. }

这是一个使用示例:

  1. package main
  2. import "fmt"
  3. func main() {
  4. fmt.Println(GetPackageName(main))
  5. }

你应该期望得到的答案是:

  1. main
英文:

Better Solution

I actually found a better solution, in this function down here you just simply pass a function and the output is gonna be simple and straight.

  1. package main
  2. import (
  3. "reflect"
  4. "runtime"
  5. "strings"
  6. )
  7. func GetPackageName(temp interface{}) string {
  8. strs := strings.Split((runtime.FuncForPC(reflect.ValueOf(temp).Pointer()).Name()), ".")
  9. strs = strings.Split(strs[len(strs)-2], "/")
  10. return strs[len(strs)-1]
  11. }

And this is an example of how you use this:

  1. package main
  2. import "fmt"
  3. func main() {
  4. fmt.Println(GetPackageName(main))
  5. }

And this is the answer you should expect:

  1. main

答案5

得分: 0

这是我一个应用程序中的一个非常低技术的解决方案,它将返回一个变量所属的包:

  1. func pkgName(x interface{}) string {
  2. varType := strings.TrimPrefix(fmt.Sprintf("%T", x), "*")
  3. return strings.TrimSuffix(varType, path.Ext(varType))
  4. }

要获取当前包,请在本地声明一个变量并将其传递进去。

英文:

Here is a very low tech solution from an application of mine, this will return the package a variable is from:

  1. func pkgName(x interface{}) string {
  2. varType := strings.TrimPrefix(fmt.Sprintf("%T", x), "*")
  3. return strings.TrimSuffix(varType, path.Ext(varType))
  4. }

To get the current package declare a variable locally and pass it in.

答案6

得分: -1

这可能会有所帮助:

  1. import (
  2. "runtime"
  3. "strings"
  4. )
  5. func Package() string {
  6. pc, _, _, _ := runtime.Caller(1)
  7. parts := strings.Split(runtime.FuncForPC(pc).Name(), ".")
  8. pl := len(parts)
  9. pkage := ""
  10. funcName := parts[pl-1]
  11. if parts[pl-2][0] == '(' {
  12. funcName = parts[pl-2] + "." + funcName
  13. pkage = strings.Join(parts[0:pl-2], ".")
  14. } else {
  15. pkage = strings.Join(parts[0:pl-1], ".")
  16. }
  17. return pkage
  18. }

这是一段Go代码,它定义了一个名为Package的函数。该函数用于获取当前函数所在的包名。它使用了runtimestrings包提供的函数来实现。

请注意,这只是代码的一部分,可能需要在其他上下文中使用。如果你有其他问题,请随时提问。

英文:

This might help:

  1. import (
  2. "runtime"
  3. "strings"
  4. )
  5. func Package() string {
  6. pc, _, _, _ := runtime.Caller(1)
  7. parts := strings.Split(runtime.FuncForPC(pc).Name(), ".")
  8. pl := len(parts)
  9. pkage := ""
  10. funcName := parts[pl-1]
  11. if parts[pl-2][0] == '(' {
  12. funcName = parts[pl-2] + "." + funcName
  13. pkage = strings.Join(parts[0:pl-2], ".")
  14. } else {
  15. pkage = strings.Join(parts[0:pl-1], ".")
  16. }
  17. return pkage
  18. }

huangapple
  • 本文由 发表于 2014年8月12日 19:08:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/25262754.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定