golang三个结构体怎么对比处理?
有三个结构体a,b,c,结构体都相同例如:
type person struct{
name string
age uint8
married bool
hobbies []string
education map [string]string
}
a和b之间有些值不同,需要获取到不同的值,经过处理,赋值到c中
这个结构体比较大,一个字段一个字段对比不太现实,我上面就是举个例子
回复
1个回答

test
2024-07-17
可以用反射自动获取结构体的成员名、成员类型、成员值,然后操作它们。
package main
import (
"fmt"
"reflect"
)
type Person struct {
Name string
Age uint8
Married bool
Hobbies []string
Education map[string]string
}
func main() {
a := Person{
Name: "John",
Age: 19,
Married: false,
Hobbies: []string{"dance", "music"},
Education: map[string]string{"university": "xx school"},
}
b := Person{
Name: "Jim",
Age: 19,
Married: false,
Hobbies: []string{"singing", "music"},
Education: map[string]string{"university": "xx school"},
}
c := Person{}
aValue := reflect.ValueOf(a)
aType := reflect.TypeOf(a)
bValue := reflect.ValueOf(b)
cValue := reflect.ValueOf(&c) // 这里要用 c 的引用,因为后面需要给 c 赋值
for i := 0; i < aValue.NumField(); i++ {
aField := aValue.Field(i) // 当前的结构体成员的 Value 对象
aFieldType := aType.Field(i) // 当前结构体成员的成员 Type,用于获取字段名称 aFieldType.Name
bField := bValue.Field(i)
fmt.Printf("%v: %v - %v\n", aFieldType.Name, aField.Interface(), bField.Interface())
fmt.Printf("========================\n")
// 切片和 map 不能直接比较,需要特殊处理。
// 处理方式要么继续用前面的反射方式,要么 interface 断言转换格式,这里用 interface 断言。
if aField.Kind() == reflect.Map {
aEdu := aField.Interface().(map[string]string)
bEdu := aField.Interface().(map[string]string)
fmt.Printf("%+v - %+v\n", aEdu, bEdu)
} else if aField.Kind() == reflect.Slice {
// 略...
} else {
// 这里我把 a b 不一样的字段按照 a 的成员直接赋值给 c,否则用 b 的成员
if aField.Interface() != bField.Interface() {
cValue.Elem().Field(i).Set(aField)
} else {
cValue.Elem().Field(i).Set(bField)
}
}
}
fmt.Printf("%+v\n", c)
}
// 结果打印如下:
Name: John - Jim
========================
Age: 19 - 19
========================
Married: false - false
========================
Hobbies: [dance music] - [singing music]
========================
Education: map[university:xx school] - map[university:xx school]
========================
map[university:xx school] - map[university:xx school]
{Name:John Age:19 Married:false Hobbies:[] Education:map[]}
代码有点长,重点内容都写了注释了。
回复

适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容