176

2 つの構造体、スライス、およびマップが等しいかどうかを確認したい。

しかし、次のコードで問題が発生しています。関連する行で私のコメントを参照してください。

package main

import (
    "fmt"
    "reflect"
)

type T struct {
    X int
    Y string
    Z []int
    M map[string]int
}

func main() {
    t1 := T{
        X: 1,
        Y: "lei",
        Z: []int{1, 2, 3},
        M: map[string]int{
            "a": 1,
            "b": 2,
        },
    }

    t2 := T{
        X: 1,
        Y: "lei",
        Z: []int{1, 2, 3},
        M: map[string]int{
            "a": 1,
            "b": 2,
        },
    }

    fmt.Println(t2 == t1)
    //error - invalid operation: t2 == t1 (struct containing []int cannot be compared)

    fmt.Println(reflect.ValueOf(t2) == reflect.ValueOf(t1))
    //false
    fmt.Println(reflect.TypeOf(t2) == reflect.TypeOf(t1))
    //true

    //Update: slice or map
    a1 := []int{1, 2, 3, 4}
    a2 := []int{1, 2, 3, 4}

    fmt.Println(a1 == a2)
    //invalid operation: a1 == a2 (slice can only be compared to nil)

    m1 := map[string]int{
        "a": 1,
        "b": 2,
    }
    m2 := map[string]int{
        "a": 1,
        "b": 2,
    }
    fmt.Println(m1 == m2)
    // m1 == m2 (map can only be compared to nil)
}

http://play.golang.org/p/AZIzW2WunI

4

7 に答える 7

192

Reflect.DeepEqualを使用するか、独自の関数を実装できます (リフレクションを使用するよりもパフォーマンスが優れています)。

http://play.golang.org/p/CPdfsYGNy_

m1 := map[string]int{   
    "a":1,
    "b":2,
}
m2 := map[string]int{   
    "a":1,
    "b":2,
}
fmt.Println(reflect.DeepEqual(m1, m2))
于 2014-07-02T14:53:36.753 に答える
101

reflect.DeepEqualあなたの質問のように、2つの同様の構造体を比較するために誤って使用されることがよくあります。

cmp.Equal構造体を比較するための優れたツールです。

リフレクションが賢明でない理由を確認するには、ドキュメントを見てみましょう。

構造体の値は、対応するフィールド (エクスポートされたフィールドとエクスポートされていないフィールドの両方) が完全に等しい場合、完全に等しいと見なされます。

....

数値、ブール値、文字列、およびチャネル - Go の == 演算子を使用して等しい場合、完全に等しいです。

time.Time同じ UTC 時間の2 つの値を比較するとt1 == t2、メタデータのタイムゾーンが異なる場合は false になります。

go-cmpメソッドを探し、Equal()それを使用して時間を正しく比較します。

例:

m1 := map[string]int{
    "a": 1,
    "b": 2,
}
m2 := map[string]int{
    "a": 1,
    "b": 2,
}
fmt.Println(cmp.Equal(m1, m2)) // will result in true

重要な注意点:

パニック状態を引き起こす可能性があるcmp.Equalため、使用する際には注意してください

パフォーマンスは目標ではなく、値を比較できない場合はパニックになる可能性があるため、テストでのみ使用することを意図しています。パニックに陥る傾向があるため、偽のパニックが致命的になる可能性がある本番環境には適していません。

于 2017-07-20T18:24:53.960 に答える