web-dev-qa-db-ja.com

名前付きの型/構造体の同等性を定義することは可能ですか?

マップでスライスを使用することについて 関連する質問 を読んだ後、Goの同等性について知りました。

Java equalsObjectメソッドをオーバーライドできることは知っています。Goがユーザー定義の型/構造体の等価性をチェックする方法を定義する同様の方法はありますか? ?その場合は、上記の問題の回避策があります interface{} values を使用すると解決策が見つかるかもしれませんが、エラーメッセージpanic: runtime error: hash of unhashable type []intを受け取りました。

33
Bill DeRose

Goは、等価性チェック構造体をサポートしています。

type Person struct {
    Name string
}

a := Person{"Bill DeRose"}
b := Person{"Bill DeRose"}

a == b // true

ポインターアドレスが異なるため、ポインターフィールド(希望する方法)では機能しません。

type Person struct {
    Friend *Person
}

a := Person{Friend: &Person{}}
b := Person{Friend: &Person{}}

a == b // false

等価演算子を変更することはできません。また、==構文を使用するカスタム型のサポートを追加する組み込みの方法はありません。代わりに、 reflect.DeepEqual を使用してポインター値を比較する必要があります。

import "reflect"

a := Person{Friend: &Person{}}
b := Person{Friend: &Person{}}

reflect.DeepEqual(a, b) // true

注意点があります。

一般的に、DeepEqualはGoの==演算子の再帰的な緩和です。ただし、このアイデアは、いくつかの不整合なしに実装することは不可能です。具体的には、値がfunc型(一般に比較不可能)であるか、浮動小数点NaN値(浮動小数点比較ではそれ自体と等しくない)であるか、またはこれは、そのような値を含む配列、構造体、またはインターフェースです。

19
AJcodez

いいえ、これはユーザーが定義することはできません。 Goには、同等と見なされるもの、および同等であるもの自体でさえも割り当て可能性に基づく厳密なルールがあります。 仕様の比較演算子セクション を見てください。

20
Volker