| package | doc | about |
|---|---|---|
async |
go.dev | Futures, promises, and deferred actions |
syncx |
go.dev | Synchronization primitives: reentrant mutex, semaphore, sync value, WithLock |
chanx |
go.dev | Channel helpers: fan-in, send/receive conversions |
errx |
go.dev | Error utilities: MultiError |
structx |
go.dev | Data structures: OrderedMap, ObjectPool |
reflectx |
go.dev | Reflection helpers: payload-size estimation |
go get github.com/lif0/pkg@latestimport (
"github.com/lif0/pkg/async"
"github.com/lif0/pkg/syncx"
"github.com/lif0/pkg/chanx"
"github.com/lif0/pkg/errx"
"github.com/lif0/pkg/structx"
"github.com/lif0/pkg/reflectx"
)Migrating from the old multi-module layout? See CHANGELOG.md for the import-path mapping. Old tags (
concurrency/v*,sync/v*,utils/v*) still resolve, so existing pins keep working.
These are small, low-level Go packages I kept rewriting from one project to the next, so I put them in one place. Most of them just fill gaps I run into in the standard library.
What I try to hold to for each one:
- Decent test coverage (around 95%+) and benchmarks where speed matters
- Few or no external dependencies
- Small, predictable APIs
- Semver tags, so you can pin a version
The module follows semver. Exported APIs are meant to stay stable, and anything breaking lands in a new major version, so it's safe to pin a version and not worry about it.
Contributions are welcome!
To contribute a package, feature, or bugfix:
- Coverage must be ≥95%
- All code must be tested and benchmarked
- Use of standard library imports is highly desirable and allowed; avoid external dependencies where possible
- APIs should be minimal, idiomatic, and efficient
- Follow Conventional Commits
To propose a new idea or package, please open an issue or discussion with:
- Motivation and use case
- Expected behavior and API shape
- Edge cases and potential risks