Getting list of exported functions from a package in golang

Let’s say I have some 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

// ./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? Argument numbers/types would be consistent across all functions in 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. I may be missing something from the godocs however, so any advice is appreciated. What I’m trying to do is essentially have a system where people can drop in .go files as a sort of “plugin”. These “plugins” will have a single exported function which the main program itself will call with a consistent number and types of args. 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

# 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

I'm abc
I'm cba

Is this possible in 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. 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. Basically I want to make it as “drop and go” as possible.

Comments 1

  • The easiest way to do this is to use the template library to parse your code and insert the new package name where appropriate.

    Playground

    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.

发表评论

电子邮件地址不会被公开。 必填项已用*标注