Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
比较除一个字段golang之外的结构_Go_Struct - Fatal编程技术网

比较除一个字段golang之外的结构

比较除一个字段golang之外的结构,go,struct,Go,Struct,我正在比较两个结构,并希望在这样做时忽略单个字段 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 =

我正在比较两个结构,并希望在这样做时忽略单个字段

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()
不允许我们忽略一个字段,一次手动比较一个字段


实现这一点的惯用方法是什么?

惯用方法是实现您自己的
func(o MyStruct)Equal(o2 MyStruct)bool
方法。

1。嵌入 一种选择是将应该参与比较的字段分组到不同的结构中,您可以将其嵌入原始结构中。进行比较时,只需比较嵌入字段:

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
}
试穿一下

如果结构不包含指针、切片、映射等,则可以使用
==
简单地比较嵌入的值。否则,请使用
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
试穿一下

另一种变体是复制一个struct值,并将其与另一个进行修改和比较,因此无需恢复原始值,这也是“更方便并发的”:

试穿这个

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
试穿这个

注意事项:

一开始这并不“友好”,因为自定义的
compare()
函数要求您检查所有涉及的字段,但其实现可能使用上述方法,例如(在上尝试):

您还可以将指针传递到
compare()
,以避免复制原始结构,例如(在上尝试):


如果您的字段已导出,您可以使用
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"))

}
主程序包
进口(
“fmt”
“反映”
)
类型Foo struct{
名称字符串
日期整数
}
func(f*Foo)EqualExcept(其他*Foo,例外字段字符串)bool{
val:=reflect.ValueOf(f).Elem()
其他字段:=reflect.Indirect(reflect.ValueOf(其他))
对于i:=0;i

这个答案为如何比较两个接口(某些字段除外)的问题提供了具体的解决方案?因为我不能
调用接口值上的reflect.Value.FieldByName
。最初的要求是我需要比较两个json字符串,除了一些字段,所以我将它们解组到接口并比较接口。
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)
}
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)
}
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"))

}