2016-12-22 16 views
2

私はスライスフィールドとFavorites構造体があります。構造体とスライスフィールドをゼロ値構造体で比較する方法はありますか?

type Favorites struct { 
    Color string 
    Lunch string 
    Place string 
    Hobbies []string 
} 

を、私は他の構造体が含まれPerson持っている:私はFavoritesフィールドがオンに設定されているかどうかを確認したいと思います

type Person struct { 
    Name string 
    Favorites Favorites 
} 

を人。他のタイプのフィールド(例えば、文字列またはint)では、そのフィールドをゼロ値(それぞれ "0"または0)と比較します。

私はエラーinvalid operation: p2.Favorites == zeroValue (struct containing []string cannot be compared)を取得し、以下のようにゼロと比較しようとした場合:

p2 := Person{Name: "Joe"} 

zeroValue := Favorites{} 
if p2.Favorites == zeroValue { 
    fmt.Println("Favorites not set") 
} 

これは仕様(https://golang.org/ref/spec#Comparison_operators)で定義されているものと一致します。

すべての単一フィールドを徹底的に比較するのではなく、この構造体が変更された場合に更新することを忘れないでください。

1つのオプションは、構造体そのものではなく構造体へのポインタを作成し、それをnilと比較することですが、これは大きなコードベースにありますので、場合。

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

+0

あなたがいないに好む理由を説明することができます'Favorites'フィールドをポインタにしますか?等価性を気にせず、単にフィールドがすべて設定されていることを確認しようとしている場合、これは最善の選択肢のようです。 – daltonclaybrook

+1

私の前のコメントに追加するには、ゼロ値を使って他のタイプの "un-set"を表すのに注意することをお勧めします。 0は 'int'フィールドのために完全に有効な値です。 – daltonclaybrook

+0

@daltonclaybrookこれは通常、最適なオプションです。構造体が全面的に使用される大きなコードベースでは、私は変更を行うことにもっと関心があります。また、構造体に構造体フィールドがたくさんある場合、ポインタを変更した場合、一貫性のためにそれらをすべて変更する必要があります。 – stephenbez

答えて

3

According to this、あなたはreflect.DeepEqual()を使用することができますが、おそらくちょうどあなた自身を記述する必要があります。

type Favorites struct { 
    Color string 
    Lunch string 
    Place string 
    Hobbies []string 
} 

func (favs *Favorites) Equals(other *Favorites) bool { 
    color_eq := favs.Color == other.Color 
    lunch_eq := favs.Lunch == other.Lunch 
    place_eq := favs.Place == other.Place 
    hobbies_eq := len(favs.Hobbies) == len(other.Hobbies) 
    if hobbies_eq { // copy slices so sorting won't affect original structs 
     f_hobbies := make([]string, len(favs.Hobbies)) 
     o_hobbies := make([]string, len(other.Hobbies)) 
     copy(favs.Hobbies, f_hobbies) 
     copy(other.Hobbies, o_hobbies) 
     sort.Strings(f_hobbies) 
     sort.Strings(o_hobbies) 
     for index, item := range f_hobbies { 
      if item != o_hobbies[index] { 
       hobbies_eq = false 
      } 
     } 
    } 
    return (color_eq && lunch_eq && place_eq && hobbies_eq) 
} 

その後でそれを呼び出す:

p2.Favorites.Equals(zeroValue) 
+0

比較の前に配列をソートする必要がありますか? –

+0

@AlexKroll良い点が編集されました。 – Will

関連する問題