如何在Golang中基于字段而不是结构类型确定结构相等性?

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

How can I determine struct equality based on fields and not struct types in Golang?

问题

我目前正在使用go-cmp包来比较结构体的相等性。出于测试目的,我需要比较两种不同类型的结构体,这些结构体应该具有相同的字段和相同的值。

作为一个最简示例,我遇到了一个问题,即cmp.Equal()函数对于不同类型的结构体返回false,即使它们具有相同的字段和值。

type s1 struct {
	Name string
}

type s2 struct {
	Name string
}

p1 := s1{Name: "John"}
p2 := s2{Name: "John"}

fmt.Println(cmp.Equal(p1, p2)) // false

这是可以理解的,因为这两种类型是不同的,但是否有办法指示cmp.Equal()忽略类型,只关注字段呢?

英文:

I am currently using the go-cmp package to compare struct equality. For testing purposes I have the need to compare two different types of structs that should have the same fields with the same values.

As a minimal example I am running into the issue where the cmp.Equal() function returns false for different types, even though they have the same fields and values.

type s1 struct {
	Name string
}

type s2 struct {
	Name string
}

p1 := s1{Name: "John"}
p2 := s2{Name: "John"}

fmt.Println(cmp.Equal(p1, p2)) // false

This is understandable since the two types are different but is there a way to instruct cmp.Equal() to ignore the types and only look at fields?

答案1

得分: 2

我不知道在比较过程中是否可以省略类型,但是如果两个结构体类型具有相同的字段,你可以将一个类型转换为另一个类型,这样就不会有问题:

p1 := s1{Name: "John"}
p2 := s2{Name: "John"}

fmt.Println(cmp.Equal(p1, p2)) // false
fmt.Println(cmp.Equal(p1, s1(p2))) // true

Go Playground上尝试一下。

英文:

I don't know if you can omit types during comparison, but if 2 struct types have identical fields, you can convert one to the other type, so this won't be an issue:

p1 := s1{Name: "John"}
p2 := s2{Name: "John"}

fmt.Println(cmp.Equal(p1, p2)) // false
fmt.Println(cmp.Equal(p1, s1(p2))) // true

Try it on the Go Playground.

答案2

得分: 0

我建议长期来看,可以创建一个名为IsS1EqualToS2的函数,逐个检查字段:

func IsS1EqualToS2(s1 s1, s2 s2) bool {
	if s1.Name != s2.Name {
		return false
	}
	return true
}

然后使用方式为:
IsS1EqualToS2(p1, p2)

英文:

What I would suggest for long term, is to have a function IsS1EqualToS2 and check the fields one-by-one:

func IsS1EqualToS2(s1 s1, s2 s2) bool {
	if s1.Name != s2.Name {
		return false
	}
	return true
}

and use as:
IsS1EqualToS2(p1, p2)

答案3

得分: 0

以下是比较字段而不考虑它们的类型的一种方法,通过将它们转换为interface类型,使用json.Marshaljson.Unmarshalcmp.Equal函数。

	type s1 struct {
		Name string
	}

	type s2 struct {
		Name string
	}

	p1 := s1{Name: "John"}
	p2 := s2{Name: "John"}

	fmt.Println(cmp.Equal(p1, p2)) // false

	var x1 interface{}
	b1, _ := json.Marshal(p1)
	_ = json.Unmarshal(b1, &x1)

	var x2 interface{}
	b2, _ := json.Marshal(p2)
	_ = json.Unmarshal(b2, &x2)

	fmt.Println(cmp.Equal(x1, x2)) // true

Playground示例

英文:

Here is one way to compare fields without their type through json.Marshal and json.Unmarshal to interface type.

	type s1 struct {
		Name string
	}

	type s2 struct {
		Name string
	}

	p1 := s1{Name: "John"}
	p2 := s2{Name: "John"}

	fmt.Println(cmp.Equal(p1, p2)) // false

	var x1 interface{}
	b1, _ := json.Marshal(p1)
	_ = json.Unmarshal(b1, &x1)

	var x2 interface{}
	b2, _ := json.Marshal(p2)
	_ = json.Unmarshal(b2, &x2)

	fmt.Println(cmp.Equal(x1, x2)) // true

Playground sample

huangapple
  • 本文由 发表于 2022年8月4日 22:16:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/73237516.html
匿名

发表评论

匿名网友

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

确定