如何在Go中通过路径从字符串导入包?

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

How to import package by path from string in Go?

问题

我有一个包名的字符串(例如"my/package/test"),我想要导入它并调用包中的某个函数。

类似这样的代码:

func init() {
  var pkg string = "test/my/pkg"
  import pkg
  pkg.Test()
}

PS. 感谢帮助

英文:

I have a string with name of package (like "my/package/test") and I wanna import that and call some function from package.

Something like this:

func init() {
  var pkg string = "test/my/pkg"
  import pkg
  pkg.Test()
}

PS. Thanks for help

答案1

得分: 6

Go语言不允许你在你的例子中提到的内容。这是一个有意的选择。在我看来,这个选择背后的原因与编译器性能和机器对代码理解的简易性有关。例如,这使得工具如gofix能够在不需要用户干预的情况下部分修复Go代码。

它还使程序员能够清楚地看到程序使用的所有静态导入的包。

另请参阅Go语言规范中有关源文件组织的语法规则。


关于在运行时动态加载包:Go不支持在运行时加载包。未来的Go运行时可能会实现这个功能(例如,golang-nuts邮件列表中偶尔会有人提出这个需求),但目前的状态是不支持这个功能。

英文:

The Go language does not allow what you mentioned in your example. This is a conscious choice. In my opinion, the reason behind this choice has to do with compiler performance and ease of code understanding by the machine. This for example enables tools such as gofix that can partially fix Go code without need for user intervention.

It also enables a programmer to clearly see all of the statically imported packages used by the program.

See also the grammar rules for source file organization in the Go language specification.


In relation to dynamically loading packages at run-time: Go has no support for loading packages at run-time. A future Go run-time might implement this feature (for example, it is occasionally being requested in messages in the golang-nuts mailing list), but the current state is that there is no support for this feature.

答案2

得分: 3

这在Go语言中是不可能的。链接器必须在编译时知道依赖关系,而你的字符串(和init函数)是在运行时评估的。此外,请注意,程序中未使用的部分,即未明确引用的部分,甚至不会成为最终二进制文件的一部分 - 因此反射也是不可能的。

如果你需要类似的功能,你必须自己管理映射。例如,你可以在一个包中使用全局映射,并使用其他包中的init函数将相关函数注册到映射中。之后,你可以使用映射来动态查找。

以http包为例。在一个虚构的博客包中,你可以使用blog.init()函数使用http.HandleFunc(pattern, handler)函数注册一些http处理程序。然后,主包可以调用http.ListenAndServe()函数,在运行时查找正确的处理程序。

英文:

That's not possible in Go. The linker has to know the dependencies at compile-time, your string (and the init-function) are however evaluated at run-time. Also note, that parts of your programs which are not used, i.e. everything which isn't referred explicitly, wont even be part of the final binary - so reflection is not possible either.

If you need something like that, you have to manage the mapping on your own. You can for example use a global map in one package and use the init functions in the other packages to register the relevant functions, by adding them to the map. After that, you can use the map to do your look-ups dynamically.

Take a look at the http package for example. In a fictional blog package you might use the blog.init() function to register a couple of http handlers using the http.HandleFunc(pattern, handler) function. The main package then might call http.ListenAndServe() which looks up the right handlers at run-time.

huangapple
  • 本文由 发表于 2011年11月10日 15:09:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/8076034.html
匿名

发表评论

匿名网友

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

确定