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

huangapple go评论91阅读模式
英文:

Is there a way to compare a struct with a slice field with the zero value struct?

问题

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

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

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

type Person struct {
    Name      string
    Favorites Favorites
}

我想检查Person上的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")
}

这与规范中定义的行为相符(https://golang.org/ref/spec#Comparison_operators)。

除了逐个比较每个字段(并在结构体更改时记得更新)之外,是否有其他方法可以进行此比较?

一种选择是将Favorites字段更改为指向结构体的指针,而不是结构体本身,然后只需与nil进行比较。但是,由于这是一个大型代码库,我不想在这种情况下进行可能影响广泛的更改。

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

英文:

I have a Favorites struct with a slice field:

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

and I have a Person which contains the other struct:

type Person struct {
	Name string
	Favorites Favorites
}

I'd like to see if the Favorites field is set on Person. For other types of fields, for example, a string or an int, I would compare that field to the zero value ("" or 0 respectively).

If I try to compare with the zero as below I get the error 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")
}

This matches what is defined in the spec (https://golang.org/ref/spec#Comparison_operators).

Is there anyway to do this comparison other than tediously comparing every single field (and having to remember to update it if the struct changes)?

One option is to make the Favorites field a pointer to the struct instead of the struct itself and then just compare with nil, but this is in a large codebase so I'd rather not make potentially far-reaching changes in this case.

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

答案1

得分: 5

根据这个链接,你可以使用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 { // 复制切片以防止排序影响原始结构体
        f_hobbies := make([]string, len(favs.Hobbies))
        o_hobbies := make([]string, len(other.Hobbies))
        copy(f_hobbies, favs.Hobbies)
        copy(o_hobbies, other.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)
}

然后使用以下方式调用:

p2.Favorites.Equals(zeroValue)
英文:

According to this, you can use reflect.DeepEqual(), but probably should just write your own:

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)
}

Then call it with:

p2.Favorites.Equals(zeroValue)

huangapple
  • 本文由 发表于 2016年12月23日 03:55:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/41290735.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定