🦁

GoでSetを扱うには?JavaのようなSetを実現する方法

2025/04/01に公開

初めに

GoではJavaのような組み込みの Set 型は提供されていません。しかし、ちょっとした工夫で簡単にSetのような振る舞いを実現することができます。

この記事では、GoでSetを扱うためにmapを活用してSetを再現する方法と、ライブラリのgo-setを使用する方法について解説します。


Setとは?

**Set(集合)**は、重複を許さず、順序を持たないデータ構造です。
Javaなどの言語では HashSetTreeSet のようなクラスが提供されており、直感的に使うことができます。

一方、Goでは組み込みのSet型がないため、map を使用してSetを再現するか、ライブラリを使用して扱います。


mapを使用してSetを再現する

標準機能でSetを作るには、以下のように map[T]struct{} を使います。

package main

import "fmt"

func main() {
	s := make(map[string]struct{})

	// 要素の追加
	s["apple"] = struct{}{}
	s["apple"] = struct{}{}
	s["banana"] = struct{}{}
	s["orange"] = struct{}{}

	// 存在チェック
	if _, exists := s["apple"]; exists {
		fmt.Println("apple は存在します")
	}

	// 要素の削除
	delete(s, "banana")

	// セット内の全要素を表示
	for v := range s {
		fmt.Println("item:", v)
	}
}

実行結果

go run main.go                                       
apple は存在します
item: apple
item: orange

ライブラリのgo-setを使用する

Setを扱えるライブラリはいくつかありますが、go-setでSetを扱います。
https://github.com/scylladb/go-set

package main

import (
	"fmt"

	"github.com/scylladb/go-set/strset"
)

func main() {
	s := strset.New()

	// 要素の追加
	s.Add("apple")
	s.Add("apple")
	s.Add("banana")
	s.Add("orange")

	// 存在チェック
	if s.Has("apple") {
		fmt.Println("apple は存在します")
	}

	// 要素の削除
	s.Remove("banana")

	// セット内の全要素を表示
	for _, v := range s.List() {
		fmt.Println("item:", v)
	}
}

実行結果

go run main.go
apple は存在します
item: apple
item: orange

最後に

いつもはmapを用いてSetを扱っていましたが、go-setの方が値の追加・削除・存在チェックのコードが少しシンプルで見やすく感じました。

ただ、重複チェック的な用途のためだけにライブラリを入れるのも少し微妙な気がするので、Goの標準機能で追加されて欲しいな、という思いはあります。

レスキューナウテックブログ

Discussion