go-forceexport is a golang package that allows access to any module-level
function, even ones that are not exported. You give it the string name of a
function , like "time.now"
, and gives you a function value that calls that
function. More generally, it can be used to achieve something like reflection on
top-level functions, whereas the reflect
package only lets you access methods
by name.
As you might expect, this library is unsafe and fragile and probably shouldn't be used in production. See "Use cases and pitfalls" below.
It has only been tested on darwin/linux amd64 with Go 1.14. If you find that it works or breaks on other platforms, feel free to submit a pull request with a fix and/or an update to this paragraph.
$ go get github.com/henrylee2cn/go-forceexport
Here's how you can grab the time.now
function, defined as
func now() (sec int64, nsec int32)
var timeNow func() (int64, int32)
err := forceexport.GetFunc(&timeNow, "time.now")
if err != nil {
// Handle errors if you care about name possibly being invalid.
}
// Calls the actual time.now function.
sec, nsec := timeNow()
The string you give should be the fully-qualified name. For example, here's
GetFunc
getting itself.
var getFunc func(interface{}, string) error
GetFunc(&getFunc, "github.com/henrylee2cn/go-forceexport.GetFunc")
This library is most useful for development and hack projects. For example, you might use it to track down why the standard library isn't behaving as you expect, or you might use it to try out a standard library function to see if it works, then later factor the code to be less fragile. You could also try using it in production; just make sure you're aware of the risks.
There are lots of things to watch out for and ways to shoot yourself in the foot:
The code is pretty short, so you could just read it, but here's a friendlier explanation:
The code uses the go:linkname
compiler directive to get the
runtime.activeModules
symbol, which is an internal function created by
the linker that's used by functions like runtime.FuncForPC
. (Using
go:linkname
is an alternate way to access unexported functions/values, but it
has other gotchas and can't be used dynamically.)
Similar to the implementation of runtime.FuncForPC
, the code walks the
function definitions until it finds one with a matching name, then gets its code
pointer.
From there, it creates a function object from the code pointer by calling
reflect.MakeFunc
and using unsafe.Pointer
to swap out the function object's
code pointer with the desired one.
Needless to say, it's a scary hack, but it seems to work!
NOTE:
//go:noinline
on the functionMIT
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。