如何在语义上比较带有嵌套切片的结构,而不管Go中元素的顺序如何

sg2wtvxw  于 2024-01-04  发布在  Go
关注(0)|答案(1)|浏览(135)

给定下一个类型结构定义:

  1. type A struct {
  2. Id int
  3. Bs []B
  4. Sub C
  5. }
  6. type B struct {
  7. Id int
  8. Str string
  9. }
  10. type C struct {
  11. Id int
  12. Ds []D
  13. }
  14. type D struct {
  15. Id int
  16. Num int
  17. }

字符串
我想测试A的下两个示例是否在语义上相等,无论切片元素在所有层次结构级别中的顺序如何。

  1. var want = &A{
  2. Id: 1,
  3. Bs: []B{{Id: 10, Str: "b10"}, {Id: 20, Str: "b20"}},
  4. Sub: C{
  5. Id: 100,
  6. Ds: []D{{Id: 101, Num: 1001}, {Id: 102, Num: 1002}},
  7. },
  8. }
  9. var got = &A{
  10. Id: 1,
  11. Bs: []B{{Id: 20, Str: "b20"}, {Id: 10, Str: "b10"}},
  12. Sub: C{
  13. Id: 100,
  14. Ds: []D{{Id: 102, Num: 1002}, {Id: 101, Num: 1001}},
  15. },
  16. }


assert比较应该返回true

4szc88ey

4szc88ey1#

cmp旨在成为reflect.DeepEqual的更强大和更安全的替代品,用于比较两个值在语义上是否相等。
这里是语义相等结构比较的完整实现,而不管切片元素在所有层次结构级别上的顺序。

文件源.go

  1. package main
  2. type A struct {
  3. Id int
  4. Bs []B
  5. Sub C
  6. }
  7. type B struct {
  8. Id int
  9. Str string
  10. }
  11. type C struct {
  12. Id int
  13. Ds []D
  14. }
  15. type D struct {
  16. Id int
  17. Num int
  18. }
  19. func NewA() *A {
  20. return &A{
  21. Id: 1,
  22. Bs: []B{{Id: 20, Str: "b20"}, {Id: 10, Str: "b10"}},
  23. Sub: C{
  24. Id: 100,
  25. Ds: []D{{Id: 102, Num: 1002}, {Id: 101, Num: 1001}},
  26. },
  27. }
  28. }

字符串

文件source_test.go

  1. package main
  2. import (
  3. "fmt"
  4. "testing"
  5. "github.com/google/go-cmp/cmp"
  6. "github.com/google/go-cmp/cmp/cmpopts"
  7. )
  8. var want = &A{
  9. Id: 1,
  10. Bs: []B{{Id: 10, Str: "b10"}, {Id: 20, Str: "b20"}},
  11. Sub: C{
  12. Id: 100,
  13. Ds: []D{{Id: 101, Num: 1001}, {Id: 102, Num: 1002}},
  14. },
  15. }
  16. func TestNewA(t *testing.T) {
  17. got := NewA()
  18. less := func(x, y any) bool {
  19. switch xv := x.(type) {
  20. case B:
  21. yv := y.(B)
  22. return fmt.Sprintf("%d-%s", xv.Id, xv.Str) < fmt.Sprintf("%d-%s", yv.Id, yv.Str)
  23. case D:
  24. yv := y.(D)
  25. return fmt.Sprintf("%d-%d", xv.Id, xv.Num) < fmt.Sprintf("%d-%d", yv.Id, yv.Num)
  26. default:
  27. return false
  28. }
  29. }
  30. if diff := cmp.Diff(want, got, cmpopts.SortSlices(less)); diff != "" {
  31. t.Errorf("mismatch:\n%s", diff)
  32. }
  33. }

展开查看全部

相关问题