vendredi 31 janvier 2020

How to type assert a dynamically reflection-generated struct interface

I'm new to Go so please bear with me if this is a trivial problem. I am using a home grown "type registry" to map type names to their type, so as to generate them dynamically based on use cases that point to the various type names (I'm basically trying for a simple solution to polymorphic Aggregation JSON response structures in Elasticsearch, but of course this could apply to many other dynamic/polymorphic situations). I'm using the solution provided by dolmen in this question: is there a way to create an instance of a struct from a string? :

var typeRegistry = make(map[string]reflect.Type)

func registerType(typedNil interface{}) {
    t := reflect.TypeOf(typedNil).Elem()
    typeRegistry[t.Name()] = t
}

func init() {
    registerType((*playlistIDAggregation)(nil))
    registerType((*srcIDAggregation)(nil))
    registerType((*assetIDAggregation)(nil))
}

func makeInstance(name string) interface{} {
    return reflect.New(typeRegistry[name]).Elem().Interface()
}

I then want to use my dynamically generated struct as the target for the JSON unmarshalling of the Aggregations node in my ES response:

playlistIDAgg := makeInstance("playlistIDAggregation")
err = json.Unmarshal(esResponse.Aggregations, &playlistIDAgg)

This isn't working like I want it to, as the Unmarshal is trying to unmarshall into an empty interface instead of the underlying struct type. it's putting the data under "data" nodes in the playlistIDAgg variable, and those data fields are of course map[string]interface{}. Am I just missing the way to type assert my playlistIDAgg interface or is there a better way to do this?





Aucun commentaire:

Enregistrer un commentaire