Редактировать: Ваше редактирование показывает, что вы хотите обрабатывать динамические объекты, которые нужно вставить / извлечь из Google Datastore.Для этого совершенно необязательно создавать типы структур во время выполнения, вы можете просто использовать динамическую карту, представленную в этом ответе: Как получить динамические свойства в хранилище данных движка приложений Google .
Ниже следует оригинальный ответ.
Обратите внимание, что если типы известны во время компиляции, лучше всего / эффективнее создавать типы и компилировать их, поэтому все будет "статичным".Вы можете создавать типы вручную или использовать go generate
для автоматизации процесса.
Также обратите внимание, что вам не обязательно нужны структурные типы для моделирования динамических объектов, много раз карт может быть достаточно.
Если типы не известны во время компиляции, и типы структур являются обязательными, читайте дальше.
Да, возможно создавать "динамические" типы структур во время выполнения , используя отражение Goв частности с функцией reflect.StructOf()
.
Давайте рассмотрим простой пример создания типа структуры во время выполнения с полем Name string
и Age int
:
t := reflect.StructOf([]reflect.StructField{
{
Name: "Name",
Type: reflect.TypeOf(""), // string
},
{
Name: "Age",
Type: reflect.TypeOf(0), // int
},
})
fmt.Println(t)
v := reflect.New(t)
fmt.Printf("%+v\n", v)
v.Elem().FieldByName("Name").Set(reflect.ValueOf("Bob"))
v.Elem().FieldByName("Age").Set(reflect.ValueOf(12))
fmt.Printf("%+v\n", v)
Это выводит (попробуйте на Go Playground ):
struct { Name string; Age int }
&{Name: Age:0}
&{Name:Bob Age:12}
Если вы хотите определить правила проверки, вы можете использовать стороннюю библиотеку для этого, дляпример github.com/go-validator/validator
.Этот пакет использует теги struct для указания правил проверки, теги struct, которые вы также можете указать с помощью отражения.
Например, если вы хотите указать, что Name
должно быть не менее 3максимум 40 символов, и он может содержать только буквы английского алфавита, а допустимый диапазон для Age
равен 6..100
(оба включительно), вот как это будет выглядеть:
t := reflect.StructOf([]reflect.StructField{
{
Name: "Name",
Type: reflect.TypeOf(""), // string
Tag: reflect.StructTag(`validate:"min=3,max=40,regexp=^[a-zA-Z]*$"`),
},
{
Name: "Age",
Type: reflect.TypeOf(0), // int
Tag: reflect.StructTag(`validate:"min=6,max=100"`),
},
})
Печать этого типа приведет к выводу (обернуто мной) (попробуйте на Go Playground ):
struct { Name string "validate:\"min=3,max=40,regexp=^[a-zA-Z]*$\"";
Age int "validate:\"min=6,max=100\"" }
После создания экземпляра этой структуры вы можете проверить его, используя validator.Validate()
функция, например:
v := reflect.New(t)
v.Elem().FieldByName("Name").Set(reflect.ValueOf("Bob"))
v.Elem().FieldByName("Age").Set(reflect.ValueOf(12))
if errs := validator.Validate(v.Elem().Interface()); errs != nil {
// values not valid, deal with errors here
}