[英]Getting list of exported functions from a package in golang
Let's say I have some package假设我有一些 package
// ./somepkg/someFile.go
package somepkg
import "fmt"
func AnExportedFunc(someArg string) {
fmt.Println("Hello world!")
fmt.Println(someArg)
)
and I import it from my main go file我从我的主 go 文件中导入它
// ./main.go
package main
import (
"./somepkg" // Let's just pretend I have the full path written out
"fmt"
)
func main() {
fmt.Println("I want to get a list of exported funcs from package 'somefolder'")
}
Is there a way to get access to the exported functions from package 'somepkg' and then to consequently call them?有没有办法从 package 'somepkg' 访问导出的函数,然后调用它们? Argument numbers/types would be consistent across all functions in somepkg.参数编号/类型在 somepkg 中的所有函数中都是一致的。 I've looked through the reflection package but I'm not sure if I can get the list and call the functions without knowing any information other than package name.我查看了反射 package 但我不确定是否可以在不知道 package 名称以外的任何信息的情况下获取列表并调用函数。 I may be missing something from the godocs however, so any advice is appreciated.但是,我可能会从 godocs 中遗漏一些东西,所以任何建议都值得赞赏。 What I'm trying to do is essentially have a system where people can drop in.go files as a sort of "plugin".我想要做的基本上是有一个人们可以加入的系统。go 文件作为一种“插件”。 These "plugins" will have a single exported function which the main program itself will call with a consistent number and types of args.这些“插件”将有一个导出的 function,主程序本身将使用一致的数量和类型的参数调用它。 Access to this codebase is restricted so there are no security concerns with arbitrary code execution by contributors.对该代码库的访问受到限制,因此贡献者的任意代码执行不存在安全问题。
Note: This is all compiled so there are no runtime restrictions注意:这是全部编译的,因此没有运行时限制
What I'm trying to do is something like this if written in python如果用 python 编写,我想做的是这样的
# test.py
def abc():
print "I'm abc"
def cba():
print "I'm cba"
and和
# foo.py
import test
flist = filter(lambda fname: fname[0] != "_", dir(test))
# Let's forget for a moment how eval() is terrible
for fname in flist:
eval("test."+fname+"()")
running foo.py returns运行 foo.py 返回
I'm abc
I'm cba
Is this possible in golang?这在golang中可能吗?
Edit:编辑:
I should note that I have already "accomplished" this with something very similar to http://mikespook.com/2012/07/function-call-by-name-in-golang/ but require that each additional "plugin" add its exported function to a package global map.我应该注意到,我已经用与http://mikespook.com/2012/07/function-call-by-name-in-golang/非常相似的东西“完成”了这一点,但要求每个额外的“插件”添加它的将 function 导出到 package 全局 map。 While this "works", this feels hacky (as if this whole program isn't... lol;) and would prefer if I could do it without requiring any additional work from the plugin writers.虽然这“有效”,但这感觉很hacky(好像整个程序不是......大声笑;)并且如果我可以在不需要插件编写者的任何额外工作的情况下完成它,我会更喜欢。 Basically I want to make it as "drop and go" as possible.基本上我想让它尽可能地“放下就走”。
The easiest way to do this is to use the template library to parse your code and insert the new package name where appropriate. 最简单的方法是使用模板库来解析代码,并在适当的地方插入新的程序包名称。
You can use this by loading all of the finals where you call the user package and then output the generated file to the execution directory. 您可以通过在调用用户包的所有决赛中加载所有总决赛,然后将生成的文件输出到执行目录来使用此功能。
As you might've guessed, it is difficult to achieve in Go, if not impossible, as Go is a compiled-language.正如您可能已经猜到的那样,在 Go 中很难实现,如果不是不可能的话,因为 Go 是一种编译语言。
Traversing a package for exported functions
can only get you the list of functions.为exported functions
遍历 package 只能得到函数列表。 A sample for this is: Playground .一个示例是: Playground 。 This is a AST (Abstract Syntax Tree) method which means calling the functions dynamically is not possible, or requires too much of workarounds.这是一种 AST(抽象语法树)方法,这意味着动态调用函数是不可能的,或者需要太多的变通方法。 Parsing function name string as function type doesn't work here.将 function 名称字符串解析为 function 类型在这里不起作用。
Alternatively, you can use try methods
by binding the exported functions to some type.或者,您可以通过将导出的函数绑定到某种类型来使用 try methods
。
type Task struct {}
func (Task) Process0()
func (Task) Process1(v int)
func (Task) Process2(v float64)
func (Task) Process3(v1 bool, v2 string)
This totally changes the way we operate as the 4 methods are now associated with a type Task
and we can pass empty instance of Task
to call the methods defined on it.这完全改变了我们的操作方式,因为这 4 个方法现在与类型Task
相关联,我们可以传递Task
的空实例来调用其上定义的方法。 This might look like just another workaround, but is very common in languages like Go.这可能看起来只是另一种解决方法,但在 Go 等语言中非常常见。 A sample for this in Playground which actually works as expected. Playground中的一个示例,它实际上按预期工作。
In both the examples, I've used multiple files in playground.在这两个示例中,我在 Playground 中使用了多个文件。 If you are not familiar with this structure, just create your workspace in your local as following and copy the code under each file name from playground:如果您不熟悉此结构,只需在本地创建工作区,如下所示,然后从 Playground 复制每个文件名下的代码:
<Your project>
├── go.mod
├── main.go
└── task
└── task.go
References:参考:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.