英文:
How to get name of current package in go?
问题
在运行时获取当前包的名称有没有办法?
package main
import "fmt"
func main() {
    pkgName := {在这里加入一些魔法}
    fmt.Println(pkgName)
}
...结果应该是"main"
目前我使用常量来实现:
package main
import "fmt"
const (
    pkgName = "main"
)
func main() {
    fmt.Println(pkgName)
}
但我想知道是否可以避免这样做。
英文:
Is there a way to get on runtime the name of current package?
package main
import "fmt"
func main() {
    pkgName := {some magic here:)}
	fmt.Println(pkgName)
}
... and the result should be "main"
Right now I'm using constant like:
package main
import "fmt"
const (
    pkgName = "main"
)
func main() {
    fmt.Println(pkgName)
}
but I'm curious if you can avoid this
答案1
得分: 39
没有 runtime 或 reflect 的方法或函数提供您所寻找的功能。
我找到的最接近的是:
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))
}
英文:
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:
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())
}
This would output:
main
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)
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))
}
答案2
得分: 31
这是我的日志记录器包的一部分。它获取有关日志函数调用者的信息,以便稍后在输出中显示。
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,
    }
}
正如你所看到的,它还返回了包名。
英文:
Here a part of my logger package. It retrieves information about the caller of the logging function to show it later in the output.
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,
	}
}
As you can see it returns the package name too.
答案3
得分: 6
要可靠地获取包名,您可以使用Go编译器的解析器仅解析包声明部分。
import (
    "fmt"
    "go/ast"
    "go/parser"
    "go/token"
)
func packageName(file string) (string, error) {
    fset := token.NewFileSet()
    // 解析Go源文件,但只解析包声明部分
    astFile, err := parser.ParseFile(fset, file, nil, parser.PackageClauseOnly)
    if err != nil {
        return "", err
    }
    if astFile.Name == nil {
        return "", fmt.Errorf("未找到包名")
    }
    return astFile.Name.Name, nil
}
以上是获取包名的代码示例。
英文:
To reliably get the package name, you can use the go compiler's parser to parse only the package clause.
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
}
答案4
得分: 1
更好的解决方案
我实际上找到了一个更好的解决方案,在下面的这个函数中,你只需要传递一个函数,输出就会变得简单明了。
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
英文:
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.
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]
}
And this is an example of how you use this:
package main
import "fmt"
func main() {
    fmt.Println(GetPackageName(main))
}
And this is the answer you should expect:
main
答案5
得分: 0
这是我一个应用程序中的一个非常低技术的解决方案,它将返回一个变量所属的包:
func pkgName(x interface{}) string {
	varType := strings.TrimPrefix(fmt.Sprintf("%T", x), "*")
	return strings.TrimSuffix(varType, path.Ext(varType))
}
要获取当前包,请在本地声明一个变量并将其传递进去。
英文:
Here is a very low tech solution from an application of mine, this will return the package a variable is from:
func pkgName(x interface{}) string {
	varType := strings.TrimPrefix(fmt.Sprintf("%T", x), "*")
	return strings.TrimSuffix(varType, path.Ext(varType))
}
To get the current package declare a variable locally and pass it in.
答案6
得分: -1
这可能会有所帮助:
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
}
这是一段Go代码,它定义了一个名为Package的函数。该函数用于获取当前函数所在的包名。它使用了runtime和strings包提供的函数来实现。
请注意,这只是代码的一部分,可能需要在其他上下文中使用。如果你有其他问题,请随时提问。
英文:
This might help:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论