Wrapper for arbitrary function in Go - go

Is it possible to create a wrapper for arbitrary function in Go that would take the same arguments and return the same value?
I'm not talking about the wrapper that would look exactly the same, it may look differently, but it should solve the problem.
For example the problem might be to create a wrapper of arbitrary function that first looks for the result of the function call in cache and only in case of cache miss executes the wrapped function.

Here's a solution using reflect.MakeFunc. This particular solution assumes that your transformation function knows what to do with every different type of function. Watch this in action: http://play.golang.org/p/7ZM4Hlcqjr
package main
import (
"fmt"
"reflect"
)
type genericFunction func(args []reflect.Value) (results []reflect.Value)
// A transformation takes a function f,
// and returns a genericFunction which should do whatever
// (ie, cache, call f directly, etc)
type transformation func(f interface{}) genericFunction
// Given a transformation, makeTransformation returns
// a function which you can apply directly to your target
// function, and it will return the transformed function
// (although in interface form, so you'll have to make
// a type assertion).
func makeTransformation(t transformation) func(interface{}) interface{} {
return func(f interface{}) interface{} {
// g is the genericFunction that transformation
// produced. It will work fine, except that it
// takes reflect.Value arguments and returns
// reflect.Value return values, which is cumbersome.
// Thus, we do some reflection magic to turn it
// into a fully-fledged function with the proper
// type signature.
g := t(f)
// typ is the type of f, and so it will also
// be the type that of the function that we
// create from the transformation (that is,
// it's essentially also the type of g, except
// that g technically takes reflect.Value
// arguments, so we need to do the magic described
// in the comment above).
typ := reflect.TypeOf(f)
// v now represents the actual function we want,
// except that it's stored in a reflect.Value,
// so we need to get it out as an interface value.
v := reflect.MakeFunc(typ, g)
return v.Interface()
}
}
func main() {
mult := func(i int) int { return i * 2 }
timesTwo := func(f interface{}) genericFunction {
return func(args []reflect.Value) (results []reflect.Value) {
// We know we'll be getting an int as the only argument,
// so this type assertion will always succeed.
arg := args[0].Interface().(int)
ff := f.(func(int) int)
result := ff(arg * 2)
return []reflect.Value{reflect.ValueOf(result)}
}
}
trans := makeTransformation(timesTwo)
// Since mult multiplies its argument by 2,
// and timesTwo transforms functions to multiply
// their arguments by 2, f will multiply its
// arguments by 4.
f := trans(mult).(func(int) int)
fmt.Println(f(1))
}

The answer based on #joshlf13 idea and answer, but seems more simple to me.
http://play.golang.org/p/v3zdMGfKy9
package main
import (
"fmt"
"reflect"
)
type (
// Type of function being wrapped
sumFuncT func(int, int) (int)
// Type of the wrapper function
wrappedSumFuncT func(sumFuncT, int, int) (int)
)
// Wrapper of any function
// First element of array is the function being wrapped
// Other elements are arguments to the function
func genericWrapper(in []reflect.Value) []reflect.Value {
// this is the place to do something useful in the wrapper
return in[0].Call(in[1:])
}
// Creates wrapper function and sets it to the passed pointer to function
func createWrapperFunction(function interface {}) {
fn := reflect.ValueOf(function).Elem()
v := reflect.MakeFunc(reflect.TypeOf(function).Elem(), genericWrapper)
fn.Set(v)
}
func main() {
var wrappedSumFunc wrappedSumFuncT
createWrapperFunction(&wrappedSumFunc)
// The function being wrapped itself
sumFunc := func (a int, b int) int {
return a + b
}
result := wrappedSumFunc(sumFunc, 1, 3)
fmt.Printf("Result is %v", result)
}

The best I've come up with is to take a function def and return an interface, which will need type assertion afterwards:
func Wrapper(metaParams string, f func() (interface{}, string, error)) (interface{}, error) {
// your wrapper code
res, metaResults, err := f()
// your wrapper code
return res, err
}
Then to use this also takes a little work to function like a wrapper:
resInterface, err := Wrapper("data for wrapper", func() (interface{}, string, error) {
res, err := YourActualFuntion(whatever, params, needed)
metaResults := "more data for wrapper"
return res, metaResults, err
}) // note f() is not called here! Pass the func, not its results
if err != nil {
// handle it
}
res, ok := resInterface.(actualType)
if !ok {
// handle it
}
The upside is this is somewhat generic, can handle anything with 1 return type + error, and doesn't require reflection.
The downside is this takes a lot of work to use as it's not a simple wrapper or decorator.

Building on previous answers and using Go's new generic capabilities, I believe this can be implemented quite elegantly (playground link):
package main
import (
"fmt"
"reflect"
)
// Creates wrapper function and sets it to the passed pointer to function
func wrapFunction[T any](function T) T {
v := reflect.MakeFunc(reflect.TypeOf(function), func(in []reflect.Value) []reflect.Value {
// This is the place to intercept your call.
fmt.Println("Params are:", in)
f := reflect.ValueOf(function)
return f.Call(in)
})
return v.Interface().(T)
}
func main() {
// The function being wrapped itself
sum := func(a int, b int) int {
return a + b
}
wrapped := wrapFunction(sum)
fmt.Printf("Result is %v", wrapped(1, 3))
}

Like this?
var cache = make(map[string]string)
func doStuff(key string) {
//do-something-that-takes-a-long-time
cache[key] = value
return value
}
fun DoStuff(key string) {
if v, ok := cache[key]; ok {
return v
}
return doStuff(key)
}

Related

Add a cache to a go function as if it were a static member

Say I have an expensive function
func veryExpensiveFunction(int) int
and this function gets called a lot for the same number.
Is there a good way to allow this function to store previous results to use if the function gets called again that is perhaps even reusable for veryExpensiveFunction2?
Obviously, it would be possible to add an argument
func veryExpensiveFunctionCached(p int, cache map[int]int) int {
if val, ok := cache[p]; ok {
return val
}
result := veryExpensiveFunction(p)
cache[p] = result
return result
}
But now I have to create the cache somewhere, where I don't care about it. I would rather have it as a "static function member" if this were possible.
What is a good way to simulate a static member cache in go?
You can use closures; and let the closure manage the cache.
func InitExpensiveFuncWithCache() func(p int) int {
var cache = make(map[int]int)
return func(p int) int {
if ret, ok := cache[p]; ok {
fmt.Println("from cache")
return ret
}
// expensive computation
time.Sleep(1 * time.Second)
r := p * 2
cache[p] = r
return r
}
}
func main() {
ExpensiveFuncWithCache := InitExpensiveFuncWithCache()
fmt.Println(ExpensiveFuncWithCache(2))
fmt.Println(ExpensiveFuncWithCache(2))
}
output:
4
from cache
4
veryExpensiveFunctionCached := InitExpensiveFuncWithCache()
and use the wrapped function with your code.
You can try it here.
If you want it to be reusable, change the signature to InitExpensiveFuncWithCache(func(int) int) so it accept a function as a parameter. Wrap it in the closure, replacing the expensive computation part with it.
You need to be careful about synchronization if this cache will be used in http handlers. In Go standard lib, each http request is processed in a dedicated goroutine and at this moment we are at the domain of concurrency and race conditions. I would suggest a RWMutex to ensure data consistency.
As for the cache injection, you may inject it at a function where you create the http handler.
Here it is a prototype
type Cache struct {
store map[int]int
mux sync.RWMutex
}
func NewCache() *Cache {
return &Cache{make(map[int]int), sync.RWMutex{}}
}
func (c *Cache) Set(id, value int) {
c.mux.Lock()
c.store[id] = id
c.mux.Unlock()
}
func (c *Cache) Get(id int) (int, error) {
c.mux.RLock()
v, ok := c.store[id]
c.mux.RUnlock()
if !ok {
return -1, errors.New("a value with given key not found")
}
return v, nil
}
func handleComplexOperation(c *Cache) http.HandlerFunc {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request){
})
}
The Go standard library uses the following style for providing "static" functions (e.g. flag.CommandLine) but which leverage underlying state:
// "static" function is just a wrapper
func Lookup(p int) int { return expCache.Lookup(p) }
var expCache = NewCache()
func newCache() *CacheExpensive { return &CacheExpensive{cache: make(map[int]int)} }
type CacheExpensive struct {
l sync.RWMutex // lock for concurrent access
cache map[int]int
}
func (c *CacheExpensive) Lookup(p int) int { /*...*/ }
this design pattern not only allows for simple one-time use, but also allows for segregated usage:
var (
userX = NewCache()
userY = NewCache()
)
userX.Lookup(12)
userY.Lookup(42)

Type that describes any go function

I want to write a function that partially applies a function to an argument, like this:
func partial(f AnyFuncType, arg interface{}) AnyFuncType {
return func(args ...interface{}) interface{} {
return f(arg, args)
}
}
type AnyFuncType func(args ...interface{}) interface{}
But that doesn't work even with the simplest function like that
func sum(a int, b int) int {
return a + b
}
func main() {
addToFive := partial(sum, 5)
}
because I get
./prog.go:16:23: cannot use sum (type func(int, int) int) as type AnyFuncType in argument to partial
compilation error. Now, I know that I could use interface{}, but is there a way to specify a more precise type for f that would work with any function?
You are trying to treat interface{} as a generic type, but interface{} is not a generic type and go will not match the signature of a function that takes interface{} as the signature of a function that takes a concrete type.
The problem is, subtyping in GO works only for interaces. Since AnyFuncType is not an interface, this won't work.
Use interface{} to represent a function of any type. There is not a more precise type that works with any function.
Use the reflect package to implement partial.
func partial(f interface{}, arg interface{}) interface{} {
v := reflect.ValueOf(f)
t := v.Type()
var in []reflect.Type
for i := 1; i < t.NumIn(); i++ {
in = append(in, t.In(i))
}
var out []reflect.Type
for i := 0; i < t.NumOut(); i++ {
out = append(out, t.Out(i))
}
var va reflect.Value
if arg != nil {
va = reflect.ValueOf(arg)
} else {
// Support `nil` as partial argument.
va = reflect.Zero(t.In(0))
}
return reflect.MakeFunc(reflect.FuncOf(in, out, t.IsVariadic()),
func(args []reflect.Value) []reflect.Value {
return v.Call(append([]reflect.Value{va}, args...))
}).Interface()
}
Use it like this:
addToFive := partial(sum, 5).(func(int) int)
fmt.Println(addToFive(1))
Run it on the playground.
I recommend using a closure to create partials instead of the partial function in this answer. The closure is more efficient and avoids tricky reflect code.
addToFive := func(x int) int { return sum(5, x) }
fmt.Println(addToFive(1))

Can I create a function with same signature as another?

I need to create a function that wraps an inner function, and has exactly the same signature as the inner function. I am fearing that this is not possible since Go does not support generics, but perhaps it is achievable using reflect? The following is the pseudo-go I would like to have:
func myFunc(a int, b string) (string, error) {
return string(a) + b, nil
}
func wrapInner(inner interface{}) interface{} {
argTypes := argsOf(inner)
returnTypes := returnsOf(inner)
wrapper := func(args argTypes) returnTypes {
// do something with inner's args
modArgs := doSomething(args)
ret := inner(modArgs)
// do something with the return
modRet := doSomething(ret)
}
return wrapper
}
wrapped := wrapInner(myFunc)
val, err := wrapped(1, "b")
The pseudo-code is full of errors, but the idea is that wrapInner has no clue about the signature of inner. However, it is able to inspect the signature (using, perhaps, reflect?) and creates a function that adds logic to inner and has exactly the same signature as inner. Is this possible?
What you are trying to achieve is the middleware pattern. It is commonly implemented with interfaces. You would have to manually implement the middleware function for every function you wish to annotate.
Here is an example:
package main
import (
"fmt"
"strconv"
)
type Service interface {
myFunc(a int, b string) (string, error)
}
type implService struct{}
func (s implService) myFunc(a int, b string) (string, error) {
return strconv.Itoa(a) + b, nil
}
type loggingMiddleware struct {
next Service
}
func (s loggingMiddleware) myFunc(a int, b string) (string, error) {
fmt.Println(a, b)
return s.next.myFunc(a, b)
}
func main() {
var myservice Service = &implService{}
myservice = &loggingMiddleware{
next: myservice,
}
result, err := myservice.myFunc(1, "a") // prints 1 a
fmt.Println(result, err) // prints 1a <nil>
}

How to call closure function obtained through reflection?

I'm experimenting with using Go's reflection library and have come to an issue I cannot figure out: How does one call on a function returned from calling a closure function via reflection? Is it possible to basically have a sequence of:
func (f someType) closureFn(i int) int {
return func (x int) int {
return x+i
}
}
...
fn := reflect.ValueOf(&f).MethodByName("closureFn")
val := append([]reflect.Value{}, reflect.ValueOf(99))
fn0 := fn.Call(val)[0]
fn0p := (*func(int) int)(unsafe.Pointer(&f0))
m := (*fn0p)(100)
Which should get m to equal 199?
The following is the simplified code that demonstrates the issue. The call to the "dummy" anonymous function works ok, as does the reflective call to the closure. However attempts at calling on the closure return fail with a nil pointer (the flag set on the address of the Value in the debugger is 147, which comes down to addressable).
Any suggestions on what's going on, or if it's at all possible are welcome.
Link to playground: https://play.golang.org/p/0EPSCXKYOp0
package main
import (
"fmt"
"reflect"
"unsafe"
)
// Typed Struct to hold the initialized jobs and group Filter function types
type GenericCollection struct {
jobs []*Generic
}
type Generic func (target int) int
func main() {
jjf := &GenericCollection{jobs: []*Generic{}}
jjf.JobFactoryCl("Type", 20)
}
// Returns job function with closure on jobtype
func (f GenericCollection) Job_by_Type_Cl(jobtype int) (func(int) int) {
fmt.Println("Job type is initialized to:", jobtype)
// Function to return
fc := func(target int) int {
fmt.Println("inside JobType function")
return target*jobtype
}
return fc
}
// Function factory
func (f GenericCollection) JobFactoryCl(name string, jobtype int) (jf func(int) int) {
fn := reflect.ValueOf(&f).MethodByName("Job_by_" + name + "_Cl")
val := append([]reflect.Value{}, reflect.ValueOf(jobtype))
if fn != reflect.ValueOf(nil) {
// Reflected function -- CALLING IT FAILS
f0 := fn.Call(val)[0]
f0p := unsafe.Pointer(&f0)
//Local dummy anonymous function - CALLING IS OK
f1 := func(i int) int {
fmt.Println("Dummy got", i)
return i+3
}
f1p := unsafe.Pointer(&f1)
// Named function
pointers := []unsafe.Pointer{f0p, f1p}
// Try running f1 - OK
f1r := (*func(int) int)(pointers[1])
fmt.Println((*f1r)(1))
(*f1r)(1)
// Try calling f0 - FAILS. nil pointer dereference
f0r := (*func(int) int)(pointers[0])
fmt.Println((*f0r)(1))
jf = *f0r
}
return jf
}
Type assert the method value to a function with the appropriate signature. Call that function.
First example from the question:
type F struct{}
func (f F) ClosureFn(i int) func(int) int {
return func(x int) int {
return x + i
}
}
func main() {
var f F
fn := reflect.ValueOf(&f).MethodByName("ClosureFn")
fn0 := fn.Call([]reflect.Value{reflect.ValueOf(99)})[0].Interface().(func(int) int)
fmt.Println(fn0(100))
// It's also possible to type assert directly
// the function type that returns the closure.
fn1 := fn.Interface().(func(int) func(int) int)
fmt.Println(fn1(99)(100))
}
Run it on the Playground
Second example from the question:
func (f GenericCollection) JobFactoryCl(name string, jobtype int) func(int) int {
jf := reflect.ValueOf(&f).MethodByName("Job_by_" + name + "_Cl").Interface().(func(int) func(int) int)
return jf(jobtype)
}
func main() {
jjf := &GenericCollection{jobs: []*Generic{}}
jf := jjf.JobFactoryCl("Type", 20)
fmt.Println(jf(10))
}
Run it on the Playground

How to define a function type which accepts any number of arguments in Go?

I try to write a function which takes any other function and wraps a new function around it. This is what I have tried so far:
package main
import (
"fmt"
)
func protect (unprotected func (...interface{})) (func (...interface{})) {
return func (args ...interface{}) {
fmt.Println ("protected");
unprotected (args...);
};
}
func main () {
a := func () {
fmt.Println ("unprotected");
};
b := protect (a);
b ();
}
When I compile this I get the error:
cannot use a (type func()) as type func(...interface { }) in function argument
Why is a function without arguments not compatible to a function with a variable number of arguments? What can I do to make them compatible?
Update:
The protected function should be compatible with the original:
func take_func_int_int (f func (x int) (y int)) (int) {
return f (1)
}
func main () {
a := func (x int) (y int) {
return 2 * x
}
b := protect (a)
take_func_int_int (a)
take_func_int_int (b)
}
Types are pretty concrete in Go. You could try
a := func(_ ...interface{}) {
fmt.Println("unprotected")
}
func (...interface{}) does not mean "any function that takes any number of any kind of arguments", it means "only a function which takes a variable number of interface{} arguments"
Alternatively rather than func(...interface{}) you can just use interface{} and the reflect package. See http://github.com/hoisie/web.go for an example.
EDIT: Specifically, this:
package main
import (
"fmt"
"reflect"
)
func protect(oldfunc interface{}) (func (...interface{})) {
if reflect.TypeOf(oldfunc).Kind() != reflect.Func {
panic("protected item is not a function")
}
return func (args ...interface{}) {
fmt.Println("Protected")
vargs := make([]reflect.Value, len(args))
for n, v := range args {
vargs[n] = reflect.ValueOf(v)
}
reflect.ValueOf(oldfunc).Call(vargs)
}
}
func main() {
a := func() {
fmt.Println("unprotected")
}
b := func(s string) {
fmt.Println(s)
}
c := protect(a)
d := protect(b)
c()
d("hello")
}
Ouput is
Protected
unprotected
Protected
hello
EDIT: To answer the update
Like I said above, types are pretty concrete in Go. The protect function returns a type func(...interface{}) which will never be assignable to func(int)int. I think you're probably either over-engineering your problem or misunderstanding it. However, here's a highly discouraged code snippet that would make it work.
First change protect to also return values:
func protect(oldfunc interface{}) (func (...interface{}) []interface{}) {
if reflect.TypeOf(oldfunc).Kind() != reflect.Func {
panic("protected item is not a function")
}
return func (args ...interface{}) []interface{} {
fmt.Println("Protected")
vargs := make([]reflect.Value, len(args))
for n, v := range args {
vargs[n] = reflect.ValueOf(v)
}
ret_vals := reflect.ValueOf(oldfunc).Call(vargs)
to_return := make([]interface{}, len(ret_vals))
for n, v := range ret_vals {
to_return[n] = v.Interface()
}
return to_return
}
}
Then make a convert function:
func convert(f func(...interface{}) (func(int) int) {
return func(x int) int {
r := f(x)
return r[0].(int)
}
}
Then your call would look like
take_func_int_int(convert(b))
But I promise this isn't what you actually want to do.
Step back and try to rework the problem. I've completely killed type-safety in these examples. What are you trying to accomplish?
package main
import "fmt"
// Here's a function that will take an arbitrary number
// of `int`s as arguments.
func sum(nums ...int) {
fmt.Print(nums, " ")
total := 0
for _, num := range nums {
total += num
}
fmt.Println(total)
}
func main() {
// Variadic functions can be called in the usual way
// with individual arguments.
sum(1, 2)
sum(1, 2, 3)
// If you already have multiple args in a slice,
// apply them to a variadic function using
// `func(slice...)` like this.
nums := []int{1, 2, 3, 4}
sum(nums...)
}

Resources