 
 Implementing Sets in Golang
A set is a collection of distinct elements that allows you to easily check for membership, add elements, and remove them without worrying about duplicates. While Go doesn’t have a built-in set type like Python or other languages, we can implement one using Go’s map type.
What is a set?
A set is a data structure that:
- Stores unique elements.
- Allows quick membership checks (i.e., whether an element exists in the set).
- Typically supports operations like union, intersection, difference, and adding/removing elements.
Implementing a set in Go
In Go, the closest thing to a set is a map with keys of the type you want in your set, and the values are just placeholders (often struct{} since it takes no memory).
Here’s how you can implement a simple set:
package main
import "fmt"
// Set is a collection of unique elements
type Set struct {
    elements map[string]struct{}
}
// NewSet creates a new set
func NewSet() *Set {
    return &Set{
        elements: make(map[string]struct{}),
    }
}
// Add inserts an element into the set
func (s *Set) Add(value string) {
    s.elements[value] = struct{}{}
}
// Remove deletes an element from the set
func (s *Set) Remove(value string) {
    delete(s.elements, value)
}
// Contains checks if an element is in the set
func (s *Set) Contains(value string) bool {
    _, found := s.elements[value]
    return found
}
// Size returns the number of elements in the set
func (s *Set) Size() int {
    return len(s.elements)
}
// List returns all elements in the set as a slice
func (s *Set) List() []string {
    keys := make([]string, 0, len(s.elements))
    for key := range s.elements {
        keys = append(keys, key)
    }
    return keys
}
// Example usage of the Set
func main() {
    set := NewSet()
    // Add elements to the set
    set.Add("apple")
    set.Add("banana")
    set.Add("orange")
    // Check if elements exist in the set
    fmt.Println("Contains 'apple':", set.Contains("apple"))  // true
    fmt.Println("Contains 'grape':", set.Contains("grape"))  // false
    // List elements
    fmt.Println("Set elements:", set.List())  // ["apple", "banana", "orange"]
    // Remove an element
    set.Remove("banana")
    fmt.Println("Set after removal:", set.List())  // ["apple", "orange"]
    // Get the size of the set
    fmt.Println("Set size:", set.Size())  // 2
}
Let’s walk through it:
- Set Struct: The set is implemented as a struct containing a map[string]struct{}. The keys of the map represent the elements of the set, and the value is an empty struct(struct{})because it takes up no memory and we don’t need to store additional data.
- Add Method: The Add method adds an element to the set by setting a key in the map. Since maps don’t allow duplicate keys, this ensures that the set only contains unique elements.
- Remove Method: The Remove method deletes an element from the set by removing the key from the map.
- Contains Method: The Contains method checks whether an element is in the set by looking up the key in the map.
- Size and List Methods: The Size method returns the number of unique elements, and the List method returns all the elements in the set as a slice.
Common Set Operations
Union
The union of two sets is a set containing all elements from both sets.
func (s *Set) Union(other *Set) *Set {
    result := NewSet()
    for key := range s.elements {
        result.Add(key)
    }
    for key := range other.elements {
        result.Add(key)
    }
    return result
}
// Example usage of Union
set1 := NewSet()
set1.Add("apple")
set1.Add("banana")
set2 := NewSet()
set2.Add("banana")
set2.Add("orange")
unionSet := set1.Union(set2)
fmt.Println("Union:", unionSet.List())  // ["apple", "banana", "orange"]
Intersection
The intersection of two sets is a set containing only the elements present in both sets.
func (s *Set) Intersection(other *Set) *Set {
    result := NewSet()
    for key := range s.elements {
        if other.Contains(key) {
            result.Add(key)
        }
    }
    return result
}
// Example usage of Intersection
intersectionSet := set1.Intersection(set2)
fmt.Println("Intersection:", intersectionSet.List())  // ["banana"]
Difference
The difference of two sets is a set containing elements that are in the first set but not in the second.
func (s *Set) Difference(other *Set) *Set {
    result := NewSet()
    for key := range s.elements {
        if !other.Contains(key) {
            result.Add(key)
        }
    }
    return result
}
// Example usage of Difference
differenceSet := set1.Difference(set2)
fmt.Println("Difference:", differenceSet.List())  // ["apple"]
Performance
The time complexity for most operations (insertion, deletion, membership check) on the set is O(1), as they are backed by a map. This means they are a great choice if they match your use case!
Wrapping up
Hope you found this useful! You may also enjoy our other blogs here with plenty more Go tips!