gointerface

golang interface matching different return types in generated code?


I have to deal with generated code - hence, it can not be changed.

func GeneratedCode(someArg string) (*GeneratedFirst, error) {
    // code does something and returns, 
        // returning an empty object just for illustration
    return &GeneratedFirst{}, nil
}

func SomeMoreGeneratedCode(someArg string) (*GeneratedSecond, error) {
    // code does something and returns
        // returning an empty object just for illustration
    return &GeneratedSecond{}, nil
}

Both GeneratedFirst and GeneratedSecond implement the same functions, hence, I wrote an interface TheInterface.

type TheInterface interface {
    FirstMethod() error
    SecondMethod() bool
    ThirdMethod() string
}

I need to call functions in a somewhat complex iteration with a range, so it is basically repeating the code, but calling different functions.

func main() {
    catchAllFn(GeneratedCode)
    catchAllFn(SomeMoreGeneratedCode)

}

I wanted to have a generic function which can receive a function, and then call it inside. Let's call this function catchAllFn.

func catchAllFn(fn func() (TheInterface, error)) error {
    // do some init logic

    // run the fn
    _, err := fn()

    // post stuff
    return err
}

The problem I am hitting is that the compiler complains with

cannot use ... (value of type func(someArg string) (*GeneratedFirst, error)) as func() (TheInterface, error) value in argument to catchAllFn

for both types.

This playground has the minimum reproducible code for the problem, without all the irrelevant details, by using just (hopefully) these descriptive names.

If the code weren't generated, I could change the returns of the functions to be the interface. But I can't.

How can I get around this problem?


Solution

  • You can use closures:

    func main() {
        catchAllFn(func(x string) (TheInterface, error) { return GeneratedCode(x) })
        catchAllFn(func(x string) (TheInterface, error) { return SomeMoreGeneratedCode(x) })
    }
    

    https://go.dev/play/p/Mc-c8nB41EC