A fast, type-safe, and easy-to-use set library for Go with three flavors to match your needs.
β¨ Three set types - Choose the behavior you need π Fast lookups - O(1) membership checks π Type-safe - Powered by Go generics π Iterator support - Works with Go 1.23+ range loops π¦ Zero dependencies - Just the Go standard library
go get github.com/spandigital/setsRequires Go 1.23 or later for iterator support.
import "github.com/spandigital/sets"
// Create a set
fruits := sets.NewSet("apple", "banana", "cherry")
// Check membership
fruits.Contains("apple") // true
// Add and remove
fruits.Add("date")
fruits.Remove("banana")
// Iterate
for fruit := range fruits.All() {
fmt.Println(fruit)
}Perfect when you just need fast lookups and don't care about order.
tags := sets.NewSet("golang", "databases", "web")
tags.Add("api")
tags.Contains("golang") // true
tags.Len() // 4
// Order is random
for tag := range tags.All() {
fmt.Println(tag) // unpredictable order
}Use when: Speed is priority and order doesn't matter.
Returns values in sorted order. Great for consistent output.
scores := sets.NewOrderedSet(95, 87, 92, 88)
for score := range scores.All() {
fmt.Println(score) // 87, 88, 92, 95
}
scores.Values() // [87, 88, 92, 95]Use when: You need sorted output (leaderboards, alphabetical lists, etc.)
Remembers the order you added items. Perfect for maintaining sequences.
steps := sets.NewInsertionOrderedSet("login", "verify", "dashboard")
steps.Add("logout")
for step := range steps.All() {
fmt.Println(step) // login, verify, dashboard, logout
}Use when: Order of insertion matters (workflows, history, etc.)
All set types support the same operations:
s := sets.NewSet(1, 2, 3)
// Basic operations
s.Add(4, 5, 6) // Add multiple items
s.Remove(2) // Remove item
s.Contains(3) // true
s.Len() // 5
s.IsEmpty() // false
s.Clear() // Remove all
// Set operations
s1 := sets.NewSet(1, 2, 3)
s2 := sets.NewSet(2, 3, 4)
s1.Union(s2) // {1, 2, 3, 4}
s1.Intersection(s2) // {2, 3}
s1.Difference(s2) // {1}
s1.Equal(s2) // falseAll sets support Go 1.23+ range-over-function iteration:
colors := sets.NewOrderedSet("red", "green", "blue")
// Standard range loop
for color := range colors.All() {
fmt.Println(color)
}
// Early termination works
for color := range colors.All() {
if color == "green" {
break // stops iteration
}
}
// Or get a slice
allColors := colors.Values() // []string{"blue", "green", "red"}| Operation | Set | OrderedSet | InsertionOrderedSet |
|---|---|---|---|
| Contains | O(1) | O(1) | O(1) |
| Add | O(1) | O(1) | O(1) amortized |
| Remove | O(1) | O(1) | O(n) |
| Values | O(n) | O(n log n) | O(n) |
| Iteration | O(n) | O(n log n) | O(n) |
items := []string{"a", "b", "a", "c", "b"}
unique := sets.NewSet(items...)
fmt.Println(unique.Values()) // [a, b, c] (random order)alice := sets.NewSet("golang", "python", "rust")
bob := sets.NewSet("python", "javascript", "rust")
common := alice.Intersection(bob)
// common contains: python, rusthistory := sets.NewInsertionOrderedSet[string]()
history.Add("home")
history.Add("search")
history.Add("profile")
history.Add("search") // duplicate, ignored
// history.All() yields: home, search, profileContributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details.
Copyright (c) 2024 Span Digital