Go 在运行时以编程方式创建结构-可能吗?
在Go中是否可以通过编程方式(即不在编译的源代码中)创建结构类型 我们有一个特定的用例,其中一个类型将通过用户定义的元数据创建,因此模式/类型事先是未知的 每一位客户的情况都会有所不同。然后,我们需要为这些服务自动生成REST服务,并将它们持久化到NoSQL后端。 我们还需要为每个字段定义不同的动态验证器,例如强制、正则表达式、最大/最小大小、最大/最小值、对其他类型实例的引用等 我想知道在旅途中是否可能有类似的事情 编辑1: 比如说 来自前端的JSON 后端 编辑:您的编辑显示您想要处理要从Google数据存储中放置/检索的动态对象。为此,完全不需要在运行时创建结构类型,您可以只使用此答案中显示的动态映射: 原来的答案如下 请注意,如果类型在编译时已知,那么最好/最有效的方法是创建类型并编译它们,因此所有内容都是静态的。您可以手动创建类型,也可以使用go generate自动执行该过程 还请注意,您可能不一定需要结构类型来建模动态对象,很多时候映射可能就足够了 如果类型在编译时未知,并且结构类型是必须的,请继续阅读 是的,可以在运行时使用Go的反射创建动态结构类型,特别是使用函数 让我们看一个简单的示例,在运行时创建一个具有名称字符串和年龄int字段的结构类型: 这将在以下位置进行尝试: 例如,如果要定义验证规则,可以使用第三方库。此包用于指定验证规则,也可以使用反射指定结构标记 例如,如果要指定名称必须至少包含3个字符,最多40个,并且只能包含英文字母表中的字母,并且年龄的有效范围为6..100(包括6..100),则如下所示:Go 在运行时以编程方式创建结构-可能吗?,go,struct,reflection,types,Go,Struct,Reflection,Types,在Go中是否可以通过编程方式(即不在编译的源代码中)创建结构类型 我们有一个特定的用例,其中一个类型将通过用户定义的元数据创建,因此模式/类型事先是未知的 每一位客户的情况都会有所不同。然后,我们需要为这些服务自动生成REST服务,并将它们持久化到NoSQL后端。 我们还需要为每个字段定义不同的动态验证器,例如强制、正则表达式、最大/最小大小、最大/最小值、对其他类型实例的引用等 我想知道在旅途中是否可能有类似的事情 编辑1: 比如说 来自前端的JSON 后端 编辑:您的编辑显示您想要处理要从G
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"`),
},
})
打印此类型将由我包装输出,请在以下位置尝试:
创建此结构的实例后,可以使用函数对其进行验证,例如:
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
}
编辑:您的编辑显示您想要处理要从Google数据存储中放置/检索的动态对象。为此,完全不需要在运行时创建结构类型,您可以只使用此答案中显示的动态映射:
原来的答案如下
请注意,如果类型在编译时已知,那么最好/最有效的方法是创建类型并编译它们,因此所有内容都是静态的。您可以手动创建类型,也可以使用go generate自动执行该过程
还请注意,您可能不一定需要结构类型来建模动态对象,很多时候映射可能就足够了
如果类型在编译时未知,并且结构类型是必须的,请继续阅读
是的,可以在运行时使用Go的反射创建动态结构类型,特别是使用函数
让我们看一个简单的示例,在运行时创建一个具有名称字符串和年龄int字段的结构类型:
这将在以下位置进行尝试:
例如,如果要定义验证规则,可以使用第三方库。此包用于指定验证规则,也可以使用反射指定结构标记
例如,如果要指定名称必须至少包含3个字符,最多40个,并且只能包含英文字母表中的字母,并且年龄的有效范围为6..100(包括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"`),
},
})
打印此类型将由我包装输出,请在以下位置尝试:
创建此结构的实例后,可以使用函数对其进行验证,例如:
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
}
我已经更新了我的答案。在上面的代码中,我将从前端获得动态JSON,如何转换为结构以将数据插入数据存储。虽然这是一个很好的解决方案,但我强烈反对使用它。这看起来像是一场噩梦,运行缓慢,最终很可能毫无意义。编译时结构或映射几乎肯定是更好的解决方案。@Adrian anysuggestion@Adrian是的,这正是我在第一段中的建议,剩下的就是回答这个问题。是的,只是第二次投票,真的,不要这样做,即使这是可能的!我已经更新了我的答案。在上面的代码中,我将从前端获得动态JSON,如何转换为结构以将数据插入数据存储。虽然这是一个很好的解决方案,但我强烈反对使用它。这看起来像是一场噩梦,运行缓慢,最终很可能毫无意义。编译时结构或映射几乎肯定是最好的
阿德里安·安尼suggestion@Adrian是的,这正是我在第一段中的建议,剩下的就是回答这个问题。是的,只是第二次投票,真的,不要这样做,即使这是可能的!
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"`),
},
})
struct { Name string "validate:\"min=3,max=40,regexp=^[a-zA-Z]*$\"";
Age int "validate:\"min=6,max=100\"" }
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
}