有没有办法将带有切片字段的结构与零值结构进行比较?

ste*_*bez 3 comparison struct go

我有一个Favorites带有切片字段的结构:

type Favorites struct {
    Color string
    Lunch string
    Place string
    Hobbies []string 
}
Run Code Online (Sandbox Code Playgroud)

我有一个Person包含其他结构的:

type Person struct {
    Name string
    Favorites Favorites
}
Run Code Online (Sandbox Code Playgroud)

我想看看该Favorites字段是否设置在“人员”上。对于其他类型的字段,例如字符串或整数,我会将该字段与零值(分别为“”或 0)进行比较。

如果我尝试与下面的零进行比较,我会收到错误invalid operation: p2.Favorites == zeroValue (struct containing []string cannot be compared)

p2 := Person{Name: "Joe"}

zeroValue := Favorites{}
if p2.Favorites == zeroValue {
    fmt.Println("Favorites not set")
}
Run Code Online (Sandbox Code Playgroud)

这与规范中定义的内容相匹配(https://golang.org/ref/spec#Comparison_operators)。

除了繁琐地比较每个字段(并且必须记住在结构发生变化时更新它)之外,还有什么办法可以进行这种比较吗?

一种选择是使“收藏夹”字段成为指向结构的指针而不是结构本身,然后仅与 nil 进行比较,但这是在一个大型代码库中,因此我不想在这种情况下进行可能影响深远的更改。

https://play.golang.org/p/d0NSp8eBes

Wil*_*ill 5

根据 this,您可以使用reflect.DeepEqual(),但可能应该编写自己的:

type Favorites struct {
    Color string
    Lunch string
    Place string
    Hobbies []string 
}

func (favs *Favorites) Equals(other *Favorites) bool {
    color_eq := favs.Color == other.Color
    lunch_eq := favs.Lunch == other.Lunch
    place_eq := favs.Place == other.Place
    hobbies_eq := len(favs.Hobbies) == len(other.Hobbies)
    if hobbies_eq {  // copy slices so sorting won't affect original structs
        f_hobbies := make([]string, len(favs.Hobbies))
        o_hobbies := make([]string, len(other.Hobbies))
        copy(favs.Hobbies, f_hobbies)
        copy(other.Hobbies, o_hobbies)
        sort.Strings(f_hobbies)
        sort.Strings(o_hobbies)
        for index, item := range f_hobbies {
            if item != o_hobbies[index] {
                hobbies_eq = false
            }
        }
    }
    return (color_eq && lunch_eq && place_eq && hobbies_eq)
}
Run Code Online (Sandbox Code Playgroud)

然后用以下方式调用它:

p2.Favorites.Equals(zeroValue)
Run Code Online (Sandbox Code Playgroud)