英文:
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.
答案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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论