golang三个结构体怎么对比处理?

有三个结构体a,b,c,结构体都相同例如:

type person struct{
    name string
    age uint8
    married bool
    hobbies []string
    education map [string]string
}

a和b之间有些值不同,需要获取到不同的值,经过处理,赋值到c中

这个结构体比较大,一个字段一个字段对比不太现实,我上面就是举个例子

阅读 2.3k
2 个回答

可以用反射自动获取结构体的成员名、成员类型、成员值,然后操作它们。

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[]}

代码有点长,重点内容都写了注释了。

不太清楚题主怎么处理值 我按自己的理解简单写了一下

type person struct {
    name      string
    age       uint8
    married   bool
    hobbies   []string
    education map[string]string
}

func CheckStruct(A person, B person) person {
    c := &person{}
    if A.married && B.married {
        c.name = A.name
        c.age = A.age
        c.married = A.married
        c.hobbies = A.hobbies
        c.education = A.education
    }
    if A.married || B.married {
        c.name = B.name
        c.age = B.age
        c.married = B.married
        c.hobbies = B.hobbies
        c.education = B.education
    }
    return *c
}
func main() {
    a := person{
        name:      "peter",
        age:       18,
        married:   true,
        hobbies:   nil,
        education: nil,
    }
    b := person{
        name:      "zhu",
        age:       19,
        married:   false,
        hobbies:   nil,
        education: nil,
    }
    fmt.Println(CheckStruct(a, b)) // {zhu 19 false [] map[]}
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题