package worker import ( "context" "fmt" "reflect" ) func getFnFromMethod(method any) (result actionFunc, err error) { // if not a function type, return error methodType := reflect.TypeOf(method) if methodType.Kind() != reflect.Func { return nil, fmt.Errorf("method must be a function") } numIn := methodType.NumIn() // if not a function with one or two arguments, return an error if numIn != 1 && numIn != 2 { return nil, fmt.Errorf("method must have one or two arguments") } // if first argument is not a context, return error firstArg := methodType.In(0) if firstArg.Kind() != reflect.Interface || !firstArg.Implements(reflect.TypeOf((*context.Context)(nil)).Elem()) { return nil, fmt.Errorf("first argument must be context.Context") } // if second argument is not a pointer to a struct, return error if numIn == 2 { secondArg := methodType.In(1) if secondArg.Kind() != reflect.Ptr { return nil, fmt.Errorf("second argument must be a pointer to a struct") } secondArgElem := secondArg.Elem() if secondArgElem.Kind() != reflect.Struct { return nil, fmt.Errorf("second argument must be a pointer to a struct") } } if methodType.NumOut() == 2 { // if first return value is not a pointer to a struct, return error firstReturn := methodType.Out(0) if firstReturn.Kind() != reflect.Ptr && firstReturn.Kind() != reflect.Interface { return nil, fmt.Errorf("first return value must be a pointer to a struct or an interface") } if firstReturn.Kind() == reflect.Ptr { firstReturnElem := firstReturn.Elem() if firstReturnElem.Kind() != reflect.Struct && firstReturnElem.Kind() != reflect.Interface { return nil, fmt.Errorf("first return value must be a pointer to a struct or an interface") } } } // if last return value is not an error, return error lastReturn := methodType.Out(methodType.NumOut() - 1) if lastReturn.Kind() != reflect.Interface || !lastReturn.Implements(reflect.TypeOf((*error)(nil)).Elem()) { return nil, fmt.Errorf("second return value must be of type error") } return func(args ...interface{}) []interface{} { // Ensure args length is correct if len(args) != 1 && len(args) != 2 { return []interface{}{nil, fmt.Errorf("expected one or two arguments, got %d", len(args))} } callArgs := []reflect.Value{ reflect.ValueOf(args[0]), } if len(args) == 2 { callArgs = append(callArgs, reflect.ValueOf(args[1])) } // Call the method with reflection values := reflect.ValueOf(method).Call(callArgs) // Return the results as an interface slice res := []interface{}{} for i := range values { res = append(res, values[i].Interface()) } return res }, nil }