github.com/linux4life798/go-forceexport@v0.0.0-20180425053403-37ebe5b408f3/README.md (about)

     1  # go-forceexport
     2  
     3  go-forceexport is a golang package that allows access to any module-level
     4  function, even ones that are not exported. You give it the string name of a
     5  function , like `"time.now"`, and gives you a function value that calls that
     6  function. More generally, it can be used to achieve something like reflection on
     7  top-level functions, whereas the `reflect` package only lets you access methods
     8  by name.
     9  
    10  As you might expect, this library is **unsafe** and **fragile** and probably
    11  shouldn't be used in production. See "Use cases and pitfalls" below.
    12  
    13  It has only been tested on Mac OS X with Go 1.6 and on GNU/Linux with
    14  Go 1.10rc2.
    15  If you find that it works or breaks on other platforms, feel free to submit
    16  a pull request with a fix and/or an update to this paragraph.
    17  
    18  ## Installation
    19  
    20  `$ go get github.com/alangpierce/go-forceexport`
    21  
    22  ## Usage
    23  
    24  Here's how you can grab the `time.now` function, defined as
    25  `func now() (sec int64, nsec int32)`
    26  
    27  ```go
    28  var timeNow func() (int64, int32)
    29  err := forceexport.GetFunc(&timeNow, "time.now")
    30  if err != nil {
    31      // Handle errors if you care about name possibly being invalid.
    32  }
    33  // Calls the actual time.now function.
    34  sec, nsec := timeNow()
    35  ```
    36  
    37  The string you give should be the fully-qualified name. For example, here's
    38  `GetFunc` getting itself.
    39  
    40  ```go
    41  var getFunc func(interface{}, string) error
    42  GetFunc(&getFunc, "github.com/alangpierce/go-forceexport.GetFunc")
    43  ```
    44  
    45  ## Use cases and pitfalls
    46  
    47  This library is most useful for development and hack projects. For example, you
    48  might use it to track down why the standard library isn't behaving as you
    49  expect, or you might use it to try out a standard library function to see if it
    50  works, then later factor the code to be less fragile. You could also try using
    51  it in production; just make sure you're aware of the risks.
    52  
    53  There are lots of things to watch out for and ways to shoot yourself in
    54  the foot:
    55  * If you define the wrong function type, you'll get a function with undefined
    56    behavior that will likely cause a runtime panic. The library makes no attempt
    57    to warn you in this case.
    58  * Calling unexported functions is inherently fragile because the function won't
    59    have any stability guarantees.
    60  * The implementation relies on the details of internal Go data structures, so
    61    later versions of Go might break this library.
    62  * Since the compiler doesn't expect unexported symbols to be used, it might not
    63    create them at all, for example due to inlining or dead code analysis. This
    64    means that functions may not show up like you expect, and new versions of the
    65    compiler may cause functions to suddenly disappear.
    66  * If the function you want to use relies on unexported types, you won't be able
    67    to trivially use it. However, you can sometimes work around this by defining
    68    equivalent copies of those types that you can use, but that approach has its
    69    own set of dangers.
    70  
    71  ## How it works
    72  
    73  The [code](/forceexport.go) is pretty short, so you could just read it, but
    74  here's a friendlier explanation:
    75  
    76  The code uses the `go:linkname` compiler directive to get access to the
    77  `runtime.firstmoduledata` symbol, which is an internal data structure created by
    78  the linker that's used by functions like `runtime.FuncForPC`. (Using
    79  `go:linkname` is an alternate way to access unexported functions/values, but it
    80  has other gotchas and can't be used dynamically.)
    81  
    82  Similar to the implementation of `runtime.FuncForPC`, the code walks the
    83  function definitions until it finds one with a matching name, then gets its code
    84  pointer.
    85  
    86  From there, it creates a function object from the code pointer by calling
    87  `reflect.MakeFunc` and using `unsafe.Pointer` to swap out the function object's
    88  code pointer with the desired one.
    89  
    90  Needless to say, it's a scary hack, but it seems to work!
    91  
    92  ## License
    93  
    94  MIT