Goのmapをsetのように使う

Go言語の標準ライブラリには他言語のset型のようなものは存在しませんが、単純なものでよければ組み込みのmapをsetのように使えます。

x := map[string]struct{}{} // string型のset相当のmapを作成
x["foobar"] = struct{}{}   // "foobar" を登録
_, ok := x["foobar"]       // ok == true。集合に値が含まれる
_, ok = x["barbaz"]        // ok == false。集合に値は含まれない

Mapのキーには比較演算子 (==!=) が定義されている型が利用できます *1(comparable*2 に近いが、mapやsliceはキーにできないのでcomparableとは異なる)。

Mapのvalueの型に空struct (struct{}) を使っているので、valueのために余計なメモリを確保せずに済みます。またこうすることでvalueに意味がないことの表明にもなります。

ただし、mapはあくまでmapなので、他言語のsetのような集合どうしの和や積などをとるためのインタフェースは存在しません。そのようなアルゴリズムが必要な場合はおとなしくdeckarep/golang-setのようなライブラリを入れるのがよいでしょう。

このテクニックは id:cockscomb さんのコードをレビューしていて知りました。