問題の歴史:
GoはデフォルトでSet構造を持っていませんが、ユニークな要素を扱う必要がある場合が多いです。その最適な構造はmap[string]struct{}で、キーが要素であり、空の構造体が「存在のマーク」となります。これは迅速なメンバーシップテストのための一般的なパターンです。
問題点:
組み込みのSetの欠如は、新人にとってユニークなコレクションを正しく実装することが難しいと感じさせます。また、なぜstruct{}がboolやintよりも値として効率的であるかを理解する必要があります。
解決策:
GoでSetを実装するためにmap[string]struct{}が使われます。空の構造体struct{}はメモリを必要とせず(ゼロサイズ)、mapは高速なアクセスを提供します。例:
set := make(map[string]struct{}) set["foo"] = struct{}{} if _, ok := set["foo"]; ok { fmt.Println("存在しています") } delete(set, "foo")
主要な特徴:
値としてslice/配列を使用できないのはなぜですか?
slice/配列はセットとして要素を探索するのに一定時間を提供せず、すべての値を順番に調べなければならないため遅くなります。
map[string]struct{}とmap[string]boolの違いは何ですか?
map[string]boolはより多くのメモリを消費します:各キーに対してboolを保存し、struct{}は空の型で何も割り当てません。
set := map[string]bool{"foo": true}
struct{}の代わりにintを使用できますか?
できますが、intは常にメモリを占めます。struct{}は汎用的で、「マーク」(存在)の役割だけが必要な場合にはより適しています。
set := map[string]int{"foo": 1} // しかし保存されるのは(キー -> 数値)
知識が不足しているため、ユニークなIPアドレスのセットにmap[string]boolを指定しました。その結果、数百万のアドレスがある場合、メモリ消費がstruct{}と比較して2倍に増えました。
長所:
短所:
プロジェクトでユニークなメールを保存するためにmap[string]struct{}を使用しました。負荷が減り、動作が速くなり、値にほとんどメモリを消費しませんでした。
長所:
短所: