GoRangeable
May 10, 2026 · View on GitHub
Reference Go implementation of Rangeable<Element> — a generic, integer-coordinate, closed-interval set container with first-insert ordered active queries.
Installation
go get github.com/ZhgChgLi/GoRangeable@v1.0.0
Standard library only — no external dependencies.
Usage
package main
import (
"fmt"
rangeable "github.com/ZhgChgLi/GoRangeable"
)
type Strong struct{}
type Italic struct{}
type Link struct{ URL string }
func main() {
r := rangeable.New[any]()
_ = r.Insert(Strong{}, 2, 5)
_ = r.Insert(Strong{}, 3, 7) // merges with [2, 5] → [2, 7]
_ = r.Insert(Strong{}, 9, 11) // disjoint
_ = r.Insert(Italic{}, 3, 8)
fmt.Println(r.GetRange(Strong{})) // [{2 7} {9 11}]
fmt.Println(r.GetRange(Italic{})) // [{3 8}]
fmt.Println(r.At(4).Objs) // [{} {}] (Strong, Italic)
fmt.Println(r.At(8).Objs) // [{}] (Italic)
}
Sweep iteration via transitions
for _, ev := range r.Transitions(0, intPtr(15)) {
coord := "+∞"
if ev.Coordinate != nil {
coord = fmt.Sprintf("%d", *ev.Coordinate)
}
fmt.Println(coord, ev.Kind, ev.Element)
}
API
| Member | Returns | Notes |
|---|---|---|
New[E comparable]() | *Rangeable[E] | empty container |
r.Insert(e, start, end) | error | returns *InvalidIntervalError on start > end |
r.At(i) | Slot[E] | Slot.Objs is the active-set slice |
r.GetRange(e) | []Interval | merged disjoint ranges |
r.Transitions(from, to *int) | []TransitionEvent[E] | to == nil means +∞ |
r.Size() | int | distinct elements |
r.IsEmpty() | bool | |
r.Each(fn) | iterates (element, intervals) | first-insert order |
r.Copy() | *Rangeable[E] | deep copy |
r.Version() | int | unchanged on idempotent insert |
Element type
Rangeable[E comparable] accepts any comparable Go type:
- Primitive types (
int,string, …) - Struct types whose fields are all comparable
- Interface types (compared by
==) - Pointer types (compared by reference)
This matches RFC §4.2 (E1–E5) — Go's built-in == is reflexive, symmetric, transitive, and consistent with the runtime hash used by maps.
type Strong struct{}
type Link struct{ URL string }
// Strong{} == Strong{} (zero-field struct equality)
// Link{"a"} == Link{"a"}
// Link{"a"} != Link{"b"}
For element types whose equivalence cannot be expressed via ==, wrap them in a comparable adapter struct.
Semantics
- End is inclusive:
Insert(e, a, b)covers[a, b], both ends. - Same-element merging: equal elements (by
==) merge on overlap or integer adjacency.[2, 4] ∪ [5, 7] = [2, 7]. - Idempotent insert: re-inserting a contained interval does not bump
Version. - Out-of-order rejected:
Insert(e, 5, 2)returns*InvalidIntervalError(matcheserrors.Is(err, ErrInvalidInterval)). - Active-set ordering: deterministic — first-insert order of the element.
- Coordinate sentinel: a close event for an interval ending at the optional
IntMaxSentinelcarriesCoordinate == nil(nil == +∞ per RFC §4.7).
See RangeableRFC § 4 for normative semantics and § 10 for the 23-case test contract.
Cross-language consistency
This Go implementation joins the Ruby, Swift, Python, JS and Kotlin implementations. All six share a 160-op / 86-probe JSON fixture and produce byte-identical outputs.
See also
- RangeableRFC — normative specification.
- RubyRangeable — Ruby reference (
gem install rangeable). - SwiftRangeable — Swift reference (SPM).
- PythonRangeable — Python reference (
pip install rangeable). - JSRangeable — TypeScript reference (
npm i rangeable-js). - KotlinRangeable — Kotlin/JVM reference (JitPack).
Development
go test ./... # run the suite
go test -run Cross ./... # cross-language fixture only
go vet ./...
The suite covers the full RFC § 10 contract, the cross-language fixture replay, and a property test against a brute-force oracle.
License
MIT (c) ZhgChgLi
Buy me a beer ❤️❤️❤️
If this project has helped you, feel free to sponsor me a cup of coffee, thank you.