Я новичок в Go, поэтому, пожалуйста, потерпите меня, если это тривиальная проблема. Я использую самодельный «реестр типов» для сопоставления имен типов с их типом, чтобы генерировать их динамически на основе вариантов использования, которые указывают на различные имена типов (в основном я пытаюсь найти простое решение для polymorphi c Агрегация JSON структур ответа в Elasticsearch, но, конечно, это может относиться ко многим другим динамическим / полиморфным c ситуациям). Я использую решение, предоставленное dolmen в этом вопросе: есть ли способ создать экземпляр структуры из строки? :
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()
}
Затем я хочу использовать свой динамически генерируемая структура в качестве цели для JSON демаршаллинга узла Aggregations в моем ответе ES:
playlistIDAgg := makeInstance("playlistIDAggregation")
err = json.Unmarshal(esResponse.Aggregations, &playlistIDAgg)
Это не работает так, как я хочу, так как Unmarshal пытается разобрать в пустой интерфейс вместо базового типа структуры. он помещает данные в узлы «data» в переменной playlistIDAgg, и эти поля данных, конечно, map[string]interface{}
. Я просто пропускаю способ ввода assert моего playlistIDAgg
интерфейса или есть лучший способ сделать это?
EDIT --- Вопросы в комментариях заставили меня понять, что редактирование этого вопроса давно назрело , В моем конкретном случае определенные мной структуры для привязки к моим агрегатам Bucket, возвращаемым Elasticsearch, имеют похожую структуру и отличаются только своим тегом root JSON, который ES использует для именования агрегата и строгого его ввода. Например,
type <name>Aggregation struct {
Agg BucketAggregationWithCamIDCardinality `json:"<name>"`
}
Итак, вместо реестра типов моя конкретная проблема может быть решена путем динамической установки тега JSON в структуре на основе конкретного варианта использования.
Кроме того, более тяжелый, но более надежный вариант - использовать клиентскую библиотеку Elasticsearch Go Оливера Эйларда, называемую Elasti c, которая имеет встроенную поддержку для всех структур отклика агрегации ES: https://github.com/olivere/elastic/