Skip to content

Instantly share code, notes, and snippets.

@tef
Created May 15, 2024 22:20
Show Gist options
  • Save tef/d6045378bbc0500fe6d2e48521225ff8 to your computer and use it in GitHub Desktop.
Save tef/d6045378bbc0500fe6d2e48521225ff8 to your computer and use it in GitHub Desktop.
func MakeFunc(out any) error {
handle := func(args []any) ([]any, error) {
// the func we're wrapping
return args
}
outFn := reflect.ValueOf(out).Elem()
outType := outFn.Type()
numOut := outType.NumOut()
lastIsError := false
if numOut > 0 {
lastArg := outType.Out(numOut - 1)
lastIsError = lastArg == typeOfError
}
newFn := reflect.MakeFunc(outType, func(in []reflect.Value) []reflect.Value {
arg := make([]any, len(in))
for i, a := range in {
arg[i] = a.Interface()
}
result, err := handle(arg...)
out := make([]reflect.Value, numOut)
for i := range out {
out[i] = reflect.Zero(outType.Out(i))
}
for i, o := range result.Values {
if i >= numOut || (lastIsError && i >= numOut-1) {
break
}
if o != nil {
v := reflect.ValueOf(o)
outType := outType.Out(i)
if outType.Kind() == v.Kind() {
out[i] = v
} else {
err = errors.New("can't unpack result")
}
}
}
if lastIsError && err != nil {
out[len(out)-1] = reflect.ValueOf(err)
}
return out
})
outFn.Set(newFn)
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment