Skip to main content
Set is a generic collection that holds at most one copy of each element. It provides membership tests, iteration, and the classic set algebra operations: union, intersection, and difference.

Installation

import "github.com/fgm/container/set"

Constructor

func NewBasicMap[E comparable](sizeHint int) container.Set[E]
sizeHint
int
required
A hint for the initial capacity of the internal map. Pass 0 if you have no estimate. This does not impose a maximum size.
s := set.NewBasicMap[string](64)
The element type E must satisfy the comparable constraint so it can be used as a map key.

Methods

Membership

MethodSignatureDescription
AddAdd(item E) (found bool)Adds item to the set. Returns true if the item was already present before this call.
RemoveRemove(item E) (found bool)Removes item from the set. Returns true if the item was present. Safe to call with a missing item.
ContainsContains(item E) boolReturns true if item is in the set.
ClearClear() (count int)Removes all elements and returns how many were removed.
ItemsItems() iter.Seq[E]Returns an iterator over all elements (unordered).
Add returns true when the item was already in the set, not when it was newly added. This mirrors a “was it found?” semantic consistent with the rest of the library. Check !found if you want to know whether insertion was new.

Set operations

MethodSignatureDescription
UnionUnion(other Set[E]) Set[E]Returns a new set containing every element from either set.
IntersectionIntersection(other Set[E]) Set[E]Returns a new set containing only elements present in both sets.
DifferenceDifference(other Set[E]) Set[E]Returns a new set containing elements in the receiver that are not in other.
For degenerate cases (nil or empty sets), Union, Intersection, and Difference may return the receiver or the argument directly without allocating a new set. Do not mutate the result if you still need the original sets to be unchanged.

Optional Countable interface

BasicMap also satisfies container.Countable, which adds a Len() method. Guard the call with a type assertion for forward compatibility:
if c, ok := s.(container.Countable); ok {
    fmt.Printf("elements in set: %d\n", c.Len())
}

Example

package main

import (
    "fmt"

    "github.com/fgm/container"
    "github.com/fgm/container/set"
)

func main() {
    evens := set.NewBasicMap[int](8)
    odds := set.NewBasicMap[int](8)

    for i := 0; i < 10; i++ {
        if i%2 == 0 {
            evens.Add(i)
        } else {
            odds.Add(i)
        }
    }

    // Check the length via the optional Countable interface.
    if c, ok := evens.(container.Countable); ok {
        fmt.Printf("even count: %d\n", c.Len())
    }

    // Contains
    fmt.Println("contains 4:", evens.Contains(4))
    fmt.Println("contains 5:", evens.Contains(5))

    // Add returns true if the item was already present.
    wasPresent := evens.Add(4)
    fmt.Println("4 was already present:", wasPresent)

    // Remove returns true if the item was present.
    wasPresent = evens.Remove(4)
    fmt.Println("4 removed (was present):", wasPresent)
    wasPresent = evens.Remove(4)
    fmt.Println("4 removed again (was present):", wasPresent)

    // Set operations.
    primes := set.NewBasicMap[int](4)
    for _, p := range []int{2, 3, 5, 7} {
        primes.Add(p)
    }

    evenPrimes := evens.Intersection(primes)
    fmt.Print("even primes: ")
    for item := range evenPrimes.Items() {
        fmt.Print(item, " ")
    }
    fmt.Println()

    allNumbers := evens.Union(odds)
    if c, ok := allNumbers.(container.Countable); ok {
        fmt.Printf("union size: %d\n", c.Len())
    }

    notPrime := evens.Difference(primes)
    fmt.Print("even non-primes: ")
    for item := range notPrime.Items() {
        fmt.Print(item, " ")
    }
    fmt.Println()
}

Iterating with Items

Items() returns an iter.Seq[E] compatible with Go 1.23+ range-over-func:
for item := range s.Items() {
    fmt.Println(item)
}
The iteration order is not guaranteed. If you need a sorted view, collect into a slice and sort it:
var slice []string
for item := range s.Items() {
    slice = append(slice, item)
}
slices.Sort(slice)
Set is not concurrency-safe. If multiple goroutines need to read or modify the same set concurrently, add external synchronization (for example, a sync.RWMutex).