set

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 28, 2025 License: MIT Imports: 7 Imported by: 0

README

go-set

A modern, performant and idiomatic set collection for Go (1.23+).

GitHub Release CI/CD codecov Go Report Card GitHub License Go Reference

Description

go-set is a modern, performant and idiomatic set collection for Go. It leverages Go 1.23+ iterators and provides a clean, standard-library-like API.

Features

  • Type Safe: Built with Go generics.
  • Iterator Support: Fully supports Go 1.23 iterators (iter.Seq).
  • Familiar API: API design similar to Go's slices package
  • Usable Zero-Value: Zero value is an empty set.
  • JSON Support: Built-in marshalling and unmarshaling.
  • Dependency Free: No external dependencies.
  • Fully Documented: Full API documentation and many examples.

Installation

go get github.com/ErikKalkoken/go-set

Quick Start

package main

import (
    "fmt"
    "github.com/ErikKalkoken/go-set"
)

func main() {
    // Initialization
    s1 := set.Of(1, 2, 3, 4)
    s2 := set.Of(3, 4, 5, 6)

    // Basic Operations
    s1.Add(7)
    s1.Delete(1)

    // Membership
    if s1.Contains(3) {
        fmt.Println("Set 1 contains 3")
    }

    // Set Algebra
    u := set.Union(s1, s2)        // {2 3 4 5 6 7}
    i := set.Intersection(s1, s2) // {3 4}
    d := set.Difference(s1, s2)   // {2 7}

    // Iterator Support (Go 1.23+)
    for v := range s1.All() {
        fmt.Println(v)
    }
}

Performance comparison

We have compared the performance of go-set (goset) with two popular set libraries:

The benchmarks measure the performance of commonly used set operations and we then compare the results of goset with golangset and k8ssets. All benchmarks were performed on a Linux amd64 system with an Intel Core i5-10210U CPU.

Our findings show that goset consistently outperforms both golangset and k8ssets across nearly every performance metric, demonstrating superior speed and memory efficiency.

Performance Summary Table
Operation Metric golangset k8ssets goset
Membership Time (sec/op) $31.835\text{ ns}$ $8.024\text{ ns}$ $7.670\text{ ns}$
Memory (B/op) $8.00\text{ B}$ $0.00\text{ B}$ $0.00\text{ B}$
Allocs (op) $1.00$ $0.00$ $0.00$
Add Time (sec/op) $267.0\text{ ns}$ $227.4\text{ ns}$ $222.6\text{ ns}$
Memory (B/op) $54.00\text{ B}$ $47.50\text{ B}$ $46.00\text{ B}$
Allocs (op) $0.00$ $0.00$ $0.00$
Remove Time (sec/op) $231.2\text{ ns}$ $197.3\text{ ns}$ $197.9\text{ ns}$
Memory (B/op) $0.00\text{ B}$ $0.00\text{ B}$ $0.00\text{ B}$
Allocs (op) $0.00$ $0.00$ $0.00$
Union Time (sec/op) $1028.5\text{ µs}$ $1045.9\text{ µs}$ $842.6\text{ µs}$
Memory (B/op) $818.1\text{ KiB}$ $818.8\text{ KiB}$ $811.8\text{ KiB}$
Allocs (op) $95.00$ $92.00$ $93.00$
Intersection Time (sec/op) $632.7\text{ µs}$ $634.7\text{ µs}$ $622.4\text{ µs}$
Memory (B/op) $289.2\text{ KiB}$ $289.2\text{ KiB}$ $289.2\text{ KiB}$
Allocs (op) $50.00$ $48.00$ $48.00$
Difference Time (sec/op) $619.3\text{ µs}$ $642.1\text{ µs}$ $620.0\text{ µs}$
Memory (B/op) $289.2\text{ KiB}$ $289.2\text{ KiB}$ $289.2\text{ KiB}$
Allocs (op) $50.00$ $48.00$ $48.00$

Key Observations
  • Speed: goset is significantly faster than golangset (especially in Membership, where it is faster) and generally outperforms or matches k8ssets.
  • Efficiency: goset eliminates memory allocations and byte usage for Membership tests compared to golangset.
  • Set Operations: For large operations like Union, goset shows a notable performance lead, being faster than both alternatives.
  • Geometric Mean: In terms of overall execution time, goset is faster than golangset and faster than k8ssets.

For more details on how the benchmarks where performed please see the related go-set-benchmark repository.

Documentation

For the full API documentation including many examples please see: Go Reference.

Documentation

Overview

Package set provides a generic set type and various related functions.

Using Set in tests

For asserting equality of sets in tests we recommend using Set.Equal as the equality comparison operator does not work and reflect.DeepEqual (e.g. used by assert.Equal) can give wrong results. The below example shows how to assert equality between sets correctly:

  if !got.Equal(want) {
	   t.Errorf("got %q, wanted %q", got, want)
  }

Zero sets

The zero value of a Set or "zero set" is an empty set ready to use. Zero sets are treated the same as empty sets and preserved (e.g. Clone, JSON marshaling).

Example
// 1. Initialization
// Create a new set of integers
s1 := set.Of(1, 2, 3, 4)
s2 := set.Of(3, 4, 5, 6)

// 2. Basic Operations
s1.Add(7)    // Add a single element
s1.Delete(1) // Remove an element

fmt.Println("Set 1:", s1) // {2 3 4 7} (Sorted in output)
fmt.Printf("Size of s1: %d\n", s1.Size())

// 3. Membership Checks
if s1.Contains(3) {
	fmt.Println("Set 1 contains 3")
}

// 4. Set Algebra (Union, Intersection, Difference)
// Union: All elements from both sets
u := set.Union(s1, s2)
fmt.Println("Union:", u) // {2 3 4 5 6 7}

// Intersection: Only elements present in both sets
i := set.Intersection(s1, s2)
fmt.Println("Intersection:", i) // {3 4}

// Difference: Elements in s1 that are NOT in s2
d := set.Difference(s1, s2)
fmt.Println("Difference (s1 - s2):", d) // {2 7}

// 5. Functional & Iterator Support (Go 1.23+)
// Use DeleteFunc to remove all even numbers
s1.DeleteFunc(func(n int) bool {
	return n%2 == 0
})
fmt.Println("s1 after deleting evens:", s1) // {3 7}
Output:

Set 1: {2 3 4 7}
Size of s1: 4
Set 1 contains 3
Union: {2 3 4 5 6 7}
Intersection: {3 4}
Difference (s1 - s2): {2 7}
s1 after deleting evens: {3 7}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Max

func Max[E comparableAndOrderable](s Set[E]) E

Max returns the maximal value in s. It panics if s is empty.

Example
s := set.Of(1, 2)
fmt.Println(set.Max(s))
Output:

2

func MaxFunc

func MaxFunc[E comparable](s Set[E], cmp func(a, b E) int) E

MaxFunc returns the maximal value in s, using cmp to compare elements. It panics if s is empty. If there is more than one maximal element according to the cmp function, MaxFunc returns the first one.

Example
s := set.Of(1, 2)
fmt.Println(set.MaxFunc(s, func(a, b int) int {
	return cmp.Compare(a, b)
}))
Output:

2

func Min

func Min[E comparableAndOrderable](s Set[E]) E

Min returns the minimal value in s. It panics if s is empty.

Example
s := set.Of(1, 2)
fmt.Println(set.Min(s))
Output:

1

func MinFunc

func MinFunc[E comparable](s Set[E], cmp func(a, b E) int) E

MinFunc returns the minimal value in s, using cmp to compare elements. It panics if s is empty. If there is more than one minimal element according to the cmp function, MinFunc returns the first one.

Example
s := set.Of(1, 2)
fmt.Println(set.MinFunc(s, func(a, b int) int {
	return cmp.Compare(a, b)
}))
Output:

1

Types

type Set

type Set[E comparable] struct {
	// contains filtered or unexported fields
}

A Set is an unordered collection of unique elements.

Sets don't need to be initialized as it's zero value is an empty set ready to use. The equality comparison operator (==) does not work for Sets. Instead Set.Equal should be used to compare sets. Set is not safe for concurrent use.

func Collect

func Collect[E comparable](seq iter.Seq[E]) Set[E]

Collect collects values from seq into a new set and returns it. If seq is empty, the result is a zero set.

Example
s := set.Collect(set.Of(1, 2, 3).All())
fmt.Println(s)
Output:

{1 2 3}

func Difference

func Difference[E comparable](s Set[E], others ...Set[E]) Set[E]

Difference constructs a new Set containing the elements of s that are not present in the union of others. When no others are provided it returns a set with the elements of s.

Example
s1 := set.Of(1, 2)
s2 := set.Of(2, 3)
fmt.Println(set.Difference(s1, s2))
Output:

{1}

func Intersection

func Intersection[E comparable](sets ...Set[E]) Set[E]

Intersection returns a new Set with elements common to all sets. When less then two sets are provided it returns an empty set.

Example
s1 := set.Of(1, 2)
s2 := set.Of(2, 3)
fmt.Println(set.Intersection(s1, s2))
Output:

{2}

func Of

func Of[E comparable](v ...E) Set[E]

Of returns a new set of the elements v. Providing no elements will return an empty and initialized set.

Example
s1 := set.Of(1, 2, 2)
s2 := set.Of([]int{3, 4}...)
s3 := set.Of[int]()
fmt.Println(s1)
fmt.Println(s2)
fmt.Println(s3)
Output:

{1 2}
{3 4}
{}

func Union

func Union[E comparable](sets ...Set[E]) Set[E]

Union returns a new Set with has the combined elements of all provided sets. When no sets are provided it returns an empty set.

Example
s1 := set.Of(1, 2)
s2 := set.Of(2, 3)
fmt.Println(set.Union(s1, s2))
Output:

{1 2 3}

func (*Set[E]) Add

func (s *Set[E]) Add(v ...E)

Add adds elements v to set s.

Example
var s set.Set[int]
s.Add(1, 2)
fmt.Println(s)
Output:

{1 2}

func (*Set[E]) AddSeq

func (s *Set[E]) AddSeq(seq iter.Seq[E])

AddSeq adds the values from seq to s.

Example
s := set.Of(1, 2)
s.AddSeq(slices.Values([]int{3, 4}))
fmt.Println(s)
Output:

{1 2 3 4}

func (Set[E]) All

func (s Set[E]) All() iter.Seq[E]

All returns on iterator over all elements of set s.

Note that the order of the elements is undefined.

Example
s := set.Of(1, 2, 3)
for x := range s.All() {
	fmt.Println(x)
}
Output:

1
2
3

func (Set[E]) Clear

func (s Set[E]) Clear()

Clear removes all elements from set s.

Example
s := set.Of(1, 2)
s.Clear()
fmt.Println(s)
Output:

{}

func (Set[E]) Clone

func (s Set[E]) Clone() Set[E]

Clone returns a new set, which contains a shallow copy of all elements of set s. Zero sets are preserved.

Example
s1 := set.Of(1, 2)
s2 := s1.Clone()
fmt.Println(s2)
Output:

{1 2}

func (Set[E]) Contains

func (s Set[E]) Contains(v E) bool

Contains reports whether element v is in set s.

Example
s := set.Of(1, 2)
fmt.Println(s.Contains(2))
fmt.Println(s.Contains(3))
Output:

true
false

func (Set[E]) ContainsAll

func (s Set[E]) ContainsAll(seq iter.Seq[E]) bool

ContainsAll reports whether all of the elements in seq are in s.

Example
s := set.Of(1, 2)
fmt.Println(s.ContainsAll(set.Of(1).All()))
fmt.Println(s.ContainsAll(set.Of(1, 2).All()))
fmt.Println(s.ContainsAll(set.Of(1, 2, 3).All()))
Output:

true
true
false

func (Set[E]) ContainsAny

func (s Set[E]) ContainsAny(seq iter.Seq[E]) bool

ContainsAny reports whether any of the elements in seq are in s.

Example
s := set.Of(1, 2)
fmt.Println(s.ContainsAny(set.Of(1).All()))
fmt.Println(s.ContainsAny(set.Of(1, 2).All()))
fmt.Println(s.ContainsAny(set.Of(1, 2, 3).All()))
fmt.Println(s.ContainsAny(set.Of(1, 3).All()))
fmt.Println(s.ContainsAny(set.Of(3, 4).All()))
Output:

true
true
true
true
false

func (Set[E]) ContainsFunc

func (s Set[E]) ContainsFunc(f func(E) bool) bool

ContainsFunc reports whether at least one element v of s satisfies f(v).

Example
s := set.Of(1, 2)
fmt.Println(s.ContainsFunc(func(x int) bool {
	return x == 2
}))
fmt.Println(s.ContainsFunc(func(x int) bool {
	return x == 3
}))
Output:

true
false

func (Set[E]) Delete

func (s Set[E]) Delete(v ...E) int

Delete removes elements v from set s. It returns the number of deleted elements. Elements that are not found in the set are ignored.

Example
s := set.Of(1, 2)
s.Delete(2)
fmt.Println(s)
Output:

{1}

func (Set[E]) DeleteFunc

func (s Set[E]) DeleteFunc(del func(E) bool) int

DeleteFunc deletes the elements in s for which del returns true. It returns the number of deleted elements.

Example
s := set.Of(1, 2)
s.DeleteFunc(func(x int) bool {
	return x == 2
})
fmt.Println(s)
Output:

{1}

func (Set[E]) DeleteSeq

func (s Set[E]) DeleteSeq(seq iter.Seq[E]) int

DeleteSeq deletes the elements in seq from s. Elements that are not present are ignored. It returns the number of deleted elements.

Example
s := set.Of(1, 2, 3)
s.DeleteSeq(set.Of(2, 3, 4).All())
fmt.Println(s)
Output:

{1}

func (Set[E]) Equal

func (s Set[E]) Equal(u Set[E]) bool

Equal reports whether sets s and u are equal. A zero set will be reported equal to an (initialized) empty set.

Example
s := set.Of(1, 2)
fmt.Println(s.Equal(set.Of(1, 2)))
fmt.Println(s.Equal(set.Of(1, 3)))
Output:

true
false

func (Set[E]) IsZero added in v0.2.0

func (s Set[E]) IsZero() bool

IsZero reports whether set s is a zero value.

Example
var s1 set.Set[int]
s2 := set.Of[int]()
fmt.Println(s1.IsZero())
fmt.Println(s2.IsZero())
Output:

true
false

func (Set[T]) MarshalJSON

func (s Set[T]) MarshalJSON() ([]byte, error)

MarshalJSON returns the JSON encoding of the set. Sets are converted to JSON arrays. Zero sets will be converted into JSON null.

func (Set[E]) Pop

func (s Set[E]) Pop() (E, bool)

Pop tries to remove and return an arbitrary element from s and reports whether it was successful.

Example
s := set.Of(1)
v, ok := s.Pop()
fmt.Println(v, ok)
_, ok = s.Pop()
fmt.Println(ok)
Output:

1 true
false

func (Set[E]) Size

func (s Set[E]) Size() int

Size returns the number of elements in set s. An empty set returns 0.

Example
s := set.Of(1, 2, 3)
fmt.Println(s.Size())
Output:

3

func (Set[E]) String

func (s Set[E]) String() string

String returns a string representation of set s. Sets are printed with curly brackets and sorted, e.g. {1 2}.

Example
s := set.Of(1, 2, 3)
fmt.Println(s)
Output:

{1 2 3}

func (*Set[T]) UnmarshalJSON

func (s *Set[T]) UnmarshalJSON(b []byte) error

UnmarshalJSON parses the JSON-encoded data b and replaces the current set. JSON null values will be unmarshaled into a zero set.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL