Maison >développement back-end >Golang >Comment appeler une fonction générique dans Go en passant un Type via réflexion
J'ai une application Go qui reçoit différentes réponses JSON pour la même API, j'ai donc essayé d'écrire un unmarshaller personnalisé qui essaiera de traiter chaque réponse JSON possible jusqu'à ce qu'il trouve la bonne réponse.
Pour ce faire, j'ai créé une fonction générique pour désorganiser JSON, et je souhaite l'appeler en utilisant le type obtenu par réflexion.
Par exemple :
package main import ( "bytes" "encoding/json" "fmt" "reflect" ) type JSONHandler struct{} func (handler *JSONHandler) Unmarshal(data []byte) error { t := reflect.TypeOf(*handler) for i := 0; i < t.NumField(); i++ { fieldType := t.Field(i) fmt.Printf("Trying to unmarshal: %s\n", fieldType.Name) result, err := unmarshal[fieldType](data) // fieldType (variable of type reflect.StructField) is not a typecompiler (NotAType) if err == nil { fmt.Printf("result: %s\n", result) break } } return nil } func unmarshal[T interface{}](data []byte) (*T, error) { obj := new(T) reader := bytes.NewReader(data) decoder := json.NewDecoder(reader) decoder.DisallowUnknownFields() err := decoder.Decode(obj) if err != nil { return nil, err } return obj, nil } type User struct { Username *string `json:"username,omitempty"` Password *string `json:"password,omitempty"` } type UserError struct { Error *string `json:"error,omitempty"` Code *int `json:"code,omitempty"` } type UserOrError struct { User *User UserError *UserError JSONHandler } var userJson = `{ "username": "[email protected]", "password": "password" }` func main() { user := new(UserOrError) result := user.Unmarshal([]byte(userJson)) // { User: something, UserError: nil } }
Cependant, le compilateur Go m'a donné cette erreur : fieldType (reflect.StructField 类型的变量) 不是类型编译器 (NotAType)
.
Existe-t-il un moyen de transmettre des paramètres de réflexion à une fonction générique ?
Cette question dépasse la portée des fonctionnalités générales de Go.
Utilisez reflect.New pour créer une valeur étant donné le reflet.Type de cette valeur. p>
Go n'a pas d'héritage. La méthode Unmarshal dans la question fonctionne sur des types qui n'ont pas de champs. Corrigé en passant le "handler" à une fonction normale.
// Unmarshal unmarshals data to each field type in handler // and returns the first successful result. The handler argument // must be a pointer to a struct. func Unmarshal(handler any, data []byte) (any, error) { t := reflect.TypeOf(handler).Elem() for i := 0; i < t.NumField(); i++ { fieldType := t.Field(i) v := reflect.New(fieldType.Type) decoder := json.NewDecoder(bytes.NewReader(data)) decoder.DisallowUnknownFields() err := decoder.Decode(v.Interface()) if err == nil { return v.Elem().Interface(), err } } return nil, errors.New("no matching type") }
Utilisez la fonction Marshal comme ceci :
type UserOrError struct { User *User UserError *UserError } var userJson = `{ "username": "<a href="https://www.php.cn/link/89fee0513b6668e555959f5dc23238e9" class="__cf_email__" data-cfemail="0e646166604e6b636f6762206d6163">[email protected]</a>", "password": "password" }` result, err := Unmarshal(&UserOrError{}, []byte(userJson)) // { User: something, UserError: nil } fmt.Printf("err=%v, result=%#v\n", err, result)
https://www.php.cn/link/c76e4b2fa54f8506719a5c0dc14c2eb9
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!