Compare structures except one golang field

I am comparing two structures and want to ignore one field at the same time.

type test struct {
  name string
  time string
} 

func main() {
  a := test{"testName", time.Now().Format(time.UnixTime)}
  // after some time
  b := test{"testName", time.Now().Format(time.UnixTime)}

  fmt.Println(a.Name == b.Name) \\ returns true Desired outcome
  fmt.Println(reflect.DeepEqual(a,b)) \\ returns false

}

reflect.DeepEqual() doesn’t allow us to ignore the field and manually compare one field at a time.

What is an idiomatic way to do this?

+4
source share
4 answers

1. With an attachment

One option is to group the fields that should take part in the comparison into another structure that you can embed in your original. When comparing, just compare the built-in fields:

type Person struct {
    Name string
    Age  int
}

type Doc struct {
    Person
    Created time.Time
}

func main() {
    d1 := Doc{
        Person:  Person{"Bob", 21},
        Created: time.Now(),
    }
    time.Sleep(time.Millisecond)
    d2 := Doc{
        Person:  Person{"Bob", 21},
        Created: time.Now(),
    }

    fmt.Println(d1 == d2)               // false
    fmt.Println(d1.Person == d2.Person) // true
}

Try it on the go playground .

, , .., ==. reflect.DeepEqual() .

2.

, : , :

a := test{"testName", time.Now().Format(time.StampMilli)}
time.Sleep(time.Millisecond)
b := test{"testName", time.Now().Format(time.StampMilli)}

// Save and make excluded fields equal:
old := a.time
a.time = b.time

fmt.Println(a.name == b.name)        // true
fmt.Println(reflect.DeepEqual(a, b)) // true

// Restore:
a.time = old

Go Playground.

, , , " ":

// Make copies and make excluded fields equal:
a2 := a
a2.time = b.time

fmt.Println(a2.name == b.name)        // true
fmt.Println(reflect.DeepEqual(a2, b)) // true

Go Playground.

3.

, :

func compare(a, b test) bool {
    return a.name == b.name
}


fmt.Println(a.name == b.name) // true
fmt.Println(compare(a, b))    // true

Go Playground.

:

"", compare() , , . ( Go Playground):

func compare(a, b test) bool {
    a.time = b.time // We're modifying a copy, so no need to make another copy
    return reflect.DeepEqual(a, b)
}

compare(), , . ( Go Playground):

fmt.Println(a.name == b.name) // true
fmt.Println(compare(&a, &b))  // true

func compare(a, b *test) bool {
    a2 := new(test)
    *a2 = *a
    a2.time = b.time
    return reflect.DeepEqual(a2, b)
}
+2

func (o MyStruct) Equal(o2 MyStruct) bool.

+8

?

, , .

0

, reflect . :.

package main

import (
    "fmt"
    "reflect"
)

type Foo struct {
    Name string
    Date int
}

func (f *Foo) EqualExcept(other *Foo, ExceptField string) bool {
    val := reflect.ValueOf(f).Elem()
    otherFields := reflect.Indirect(reflect.ValueOf(other))

    for i := 0; i < val.NumField(); i++ {
        typeField := val.Type().Field(i)
        if typeField.Name == ExceptField {
            continue
        }

        value := val.Field(i)
        otherValue := otherFields.FieldByName(typeField.Name)

        if value.Interface() != otherValue.Interface() {
            return false
        }
    }
    return true
}

func main() {
    f := &Foo{
        "Drew",
        30,
    }

    f2 := &Foo{
        "Drew",
        50,
    }

    fmt.Println(f.EqualExcept(f2, "Date"))
    fmt.Println(f.EqualExcept(f2, "Name"))

}

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

0

Source: https://habr.com/ru/post/1688791/


All Articles