Maison  >  Article  >  développement back-end  >  Comment exécuter un rappel de type générique soumis à plusieurs types de retour ?

Comment exécuter un rappel de type générique soumis à plusieurs types de retour ?

WBOY
WBOYavant
2024-02-12 17:06:05696parcourir

Comment exécuter un rappel de type générique soumis à plusieurs types de retour ?

Contenu de la question

J'essaie d'autoriser un paramètre de rappel dans ma fonction qui permet plusieurs tuples de retour. Pour y parvenir, j'utilise des génériques pour définir les types de paramètres du rappel.

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.
}

Étant donné que translatefn est limité à l'un ou l'autre de ces deux types de retour (out(out, error)), j'ai pensé pouvoir l'appeler.

Ce que je veux faire est quelque chose comme ci-dessous, mais je ne peux pas car je ne peux pas utiliser d'assertion de type sur le paramètre translate.

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")
}

Comment puis-je appeler ce rappel sans assertion de type, ou déterminer quelles variantes courantes sont fournies ?

Solution de contournement

Enveloppez-le d'abord dans une interface, puis effectuez une assertion de type (ou un changement de type). Par exemple. 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")
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer