Home >Backend Development >Golang >How to execute a callback of type generic that is subject to multiple return types?

How to execute a callback of type generic that is subject to multiple return types?

WBOY
WBOYforward
2024-02-12 17:06:05725browse

How to execute a callback of type generic that is subject to multiple return types?

Question content

I am trying to allow a callback parameter in my function that allows for multiple return tuples. To achieve this, I use generics to define the callback's parameter types.

func get[
    in any,
    out any,
    translatefn func(in) out | func(in) (out, error),
](
    input in,
    translate translatefn,
) (*out, error) {
    // call translate to convert the input to the output.
    // if translate is an erroring function, make sure the error is
    // forwarded to the response of this function.
}

Since translatefn is limited to either of these two return types (out or (out, error)), I thought I would be able to call it.

What I want to do is something like the following, but I can't because I can't use a type assertion on the translate parameter.

invalid operation: cannot use type assertion on type parameter value translate (variable of type translatefn constrained by func(in) out|func(in) (out, error))
func Get[
    In any,
    Out any,
    TranslateFn func(In) Out | func(In) (Out, error),
](
    input In,
    translate TranslateFn,
) (*Out, error) {
    if erroringFn, isErroringTranslateFn := translate.(func(In) (Out, error)); isErroringTranslateFn {
        out, err := erroringFn(input)
        if err != nil {
            return nil, err
        }
        return &out, nil
    }

    if nonErroringFn, isNonErroringTranslateFn := translate.(func(In) Out); isNonErroringTranslateFn {
        out, err := nonErroringFn(input)
        if err != nil {
            return nil, err
        }
        return &out, nil
    }

    panic("translate function must be either func(In) (Out, error) or func(In) Out")
}

Without type assertions, how would I call this callback, or determine what common variants are provided?

Solution

First wrap it into an interface, and then do type assertion (or type switching). For example. any(v).(t)

func Get[
    In any,
    Out any,
    TranslateFn func(In) Out | func(In) (Out, error),
](
    input In,
    translate TranslateFn,
) (*Out, error) {
    switch f := any(translate).(type) {
    case func(In) (Out, error):
        out, err := f(input)
        if err != nil {
            return nil, err
        }
        return &out, nil
    case func(In) Out:
        out := f(input)
        return &out, nil
    }

    panic("shouldn't happen")
}

The above is the detailed content of How to execute a callback of type generic that is subject to multiple return types?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete