具有动态类型结构的 Go 函数
Go function with dynamic types of structures
有人可以帮我吗:我需要为不同类型的结构设置字段值。我有一张包含数据的地图,是从数据库中提取的。在这个特定的函数中,我想创建一个任何结构的对象,其字段与映射匹配
type Member struct {
firstName string `xml: "FIRST_NAME"`
lastName string `xml: "LAST_NAME"`
}
type CardData struct {
cardType string `xml: "CARD_TYPE"`
cardNumber string `xml: "CARD_NUMBER"`
}
func main() {
fields := make(map[string]string)
fields['CARD_TYPE'] = "VISA"
fields['FIRS_NAME'] = "Aria Stark"
member := Combiner(fields, Member{})
card := Combiner(fields, CardData{})
}
func Combiner(m map[string]string, obj interface{}) interface{} {
ff := reflect.ValueOf(obj)
typeOfS := ff.Type()
for i := 0; i< ff.NumField(); i++ {
tag := typeOfS.Field(i).Tag.Get("xml")
if _, ok := m[tag]; ok {
n := typeOfS.Field(i).Name
reflections.SetField(&obj, n, m[tag])
} else {
fmt.Printf("The field %s is not found \n", tag)
}
}
return obj
}
但是我在这个字符串“reflections.SetField(&obj, n, m[tag])”中得到一个错误
它不起作用,因为“obj”不是结构
非常感谢您的所有回答!
您必须将指向该对象的指针传递给您的 Combiner 函数。来自 reflections.SetFields
的文档:
obj param has to be a pointer to a struct, otherwise it will soundly
fail.
所以:
member := Combiner(fields, &Member{})
card := Combiner(fields, &CardData{})
和内部 Combiner
:
reflections.SetField(obj, n, m[tag])
您接近正确的解决方案。代码的问题是:
- 字符串引号字符是
"
,不是'
。
- 标准结构字段标签中冒号后没有space。
- 无法设置非导出字段。
- 要在字段上设置值,反射值必须具有可寻址值。
这是修复了问题的代码:
type Member struct {
// NOTE: Export by capitalizing first letter in field name.
// NOTE: Remove space after the :
FirstName string `xml:"FIRST_NAME"`
LastName string `xml:"LAST_NAME"`
}
type CardData struct {
CardType string `xml:"CARD_TYPE"`
CardNumber string `xml:"CARD_NUMBER"`
}
func main() {
fields := make(map[string]string)
// NOTE: use " instead of '
fields["CARD_TYPE"] = "VISA"
fields["FIRST_NAME"] = "Aria Stark"
// NOTE: Pass pointer to struct so that combiner
// has an addressable value.
member := Combiner(fields, &Member{})
card := Combiner(fields, &CardData{})
fmt.Println(member)
fmt.Println(card)
}
func Combiner(m map[string]string, obj interface{}) interface{} {
// NOTE: dereference the pointer by calling Elem()
ff := reflect.ValueOf(obj).Elem()
typeOfS := ff.Type()
for i := 0; i < ff.NumField(); i++ {
tag := typeOfS.Field(i).Tag.Get("xml")
if _, ok := m[tag]; ok {
// NOTE: Set the field directly using the reflect package.
ff.Field(i).Set(reflect.ValueOf(m[tag]))
} else {
fmt.Printf("The field %s is not found \n", tag)
}
}
return obj
}
有人可以帮我吗:我需要为不同类型的结构设置字段值。我有一张包含数据的地图,是从数据库中提取的。在这个特定的函数中,我想创建一个任何结构的对象,其字段与映射匹配
type Member struct {
firstName string `xml: "FIRST_NAME"`
lastName string `xml: "LAST_NAME"`
}
type CardData struct {
cardType string `xml: "CARD_TYPE"`
cardNumber string `xml: "CARD_NUMBER"`
}
func main() {
fields := make(map[string]string)
fields['CARD_TYPE'] = "VISA"
fields['FIRS_NAME'] = "Aria Stark"
member := Combiner(fields, Member{})
card := Combiner(fields, CardData{})
}
func Combiner(m map[string]string, obj interface{}) interface{} {
ff := reflect.ValueOf(obj)
typeOfS := ff.Type()
for i := 0; i< ff.NumField(); i++ {
tag := typeOfS.Field(i).Tag.Get("xml")
if _, ok := m[tag]; ok {
n := typeOfS.Field(i).Name
reflections.SetField(&obj, n, m[tag])
} else {
fmt.Printf("The field %s is not found \n", tag)
}
}
return obj
}
但是我在这个字符串“reflections.SetField(&obj, n, m[tag])”中得到一个错误 它不起作用,因为“obj”不是结构
非常感谢您的所有回答!
您必须将指向该对象的指针传递给您的 Combiner 函数。来自 reflections.SetFields
的文档:
obj param has to be a pointer to a struct, otherwise it will soundly fail.
所以:
member := Combiner(fields, &Member{})
card := Combiner(fields, &CardData{})
和内部 Combiner
:
reflections.SetField(obj, n, m[tag])
您接近正确的解决方案。代码的问题是:
- 字符串引号字符是
"
,不是'
。 - 标准结构字段标签中冒号后没有space。
- 无法设置非导出字段。
- 要在字段上设置值,反射值必须具有可寻址值。
这是修复了问题的代码:
type Member struct {
// NOTE: Export by capitalizing first letter in field name.
// NOTE: Remove space after the :
FirstName string `xml:"FIRST_NAME"`
LastName string `xml:"LAST_NAME"`
}
type CardData struct {
CardType string `xml:"CARD_TYPE"`
CardNumber string `xml:"CARD_NUMBER"`
}
func main() {
fields := make(map[string]string)
// NOTE: use " instead of '
fields["CARD_TYPE"] = "VISA"
fields["FIRST_NAME"] = "Aria Stark"
// NOTE: Pass pointer to struct so that combiner
// has an addressable value.
member := Combiner(fields, &Member{})
card := Combiner(fields, &CardData{})
fmt.Println(member)
fmt.Println(card)
}
func Combiner(m map[string]string, obj interface{}) interface{} {
// NOTE: dereference the pointer by calling Elem()
ff := reflect.ValueOf(obj).Elem()
typeOfS := ff.Type()
for i := 0; i < ff.NumField(); i++ {
tag := typeOfS.Field(i).Tag.Get("xml")
if _, ok := m[tag]; ok {
// NOTE: Set the field directly using the reflect package.
ff.Field(i).Set(reflect.ValueOf(m[tag]))
} else {
fmt.Printf("The field %s is not found \n", tag)
}
}
return obj
}