Introduction
Notes on implementing the Set data structure while recently migrating from JavaScript to Go. The previous code used JavaScript Set to enforce unique items, but Go doesn’t have a built-in Set; we can implement it by adapting maps.
Set Definition
A data structure where elements are unique, used to represent a collection of non-duplicate values
- Elements are unique
- Typically allows fast membership checks (e.g.,:
set.has('foobar'),O(1)) - Typically does not emphasize order or indexing
Implementing a Set with Maps
The simplest way to deduplicate data is to put everything into a map; repeated inserts are harmless:
s := map[int]bool{5: true, 2: true}_, ok := s[6] // Check is exists[8] = true // Adddelete(s, 2) // DeleteUsing an empty struct that occupies no space
set := make(map[string]struct{})The reason is struct occupies no memory, while bool still requires 1 byte. When a Set stores many elements, using struct can save memory effectively.
Generic version
type Set[T comparable] struct { m map[T]struct{}}
func NewSet[T comparable]() *Set[T] { return &Set[T]{m: make(map[T]struct{})}}
func (s *Set[T]) Add(v T) { s.m[v] = struct{}{}}
func (s *Set[T]) Has(v T) bool { _, ok := s.m[v] return ok}
func (s *Set[T]) Remove(v T) { delete(s.m, v)}
func (s *Set[T]) Len() int { return len(s.m)}Further reading
- Golang why don’t we have a set datastructure [closed] - Stack Overflow
- Why 0 bytes matter: Using Empty Structs in Go