README
¶
utils
General-purpose utility libraries for Go applications.
Overview
This module provides eight focused utility packages for common Go programming tasks:
- base62 - Base62 encoding/decoding for int64 values
- xcrypto - HMAC-SHA256 cryptographic functions
- cookie - HTTP Cookie header parsing and formatting
- xemail - Email address syntax validation
- xgo - Panic-safe goroutine execution
- xmap - Deep map merge, map normalization, and path-based lookup
- xnet - Local network address selection and random TCP listen helpers
- xsync - Concurrency primitives (event, unbounded FIFO queue, serializer)
All packages are production-ready with comprehensive tests, benchmarks, and zero external dependencies.
Installation
go get github.com/codesjoy/pkg/utils
Packages
base62 - Base62 Encoding
Encode and decode int64 values to/from base62 strings using the alphabet abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.
Use Cases:
- URL-safe ID generation
- Short URL services
- ID obfuscation
- Compact numeric representation
Example:
import "github.com/codesjoy/pkg/utils/base62"
// Encode an integer to base62
encoded, err := base62.EncodeInt64(123456789)
// encoded = "iwaUH"
// Decode back to integer
decoded, err := base62.DecodeInt64("iwaUH")
// decoded = 123456789
// Handles full int64 range
maxEncoded, _ := base62.EncodeInt64(math.MaxInt64)
// maxEncoded = "k9viXaIfiWh"
API:
EncodeInt64(n int64) (string, error)- Convert int64 to base62 stringDecodeInt64(s string) (int64, error)- Convert base62 string to int64
Errors:
ErrNegativeNumber- Negative numbers are not supportedErrEmptyString- Cannot decode empty stringErrInvalidCharacter- String contains non-base62 charactersErrOverflow- Decoded value exceeds int64 range
xcrypto - Cryptographic Functions
Compute HMAC-SHA256 hashes for message authentication and data integrity verification.
Use Cases:
- API signature verification
- Token generation and validation
- Data integrity checks
- Secure message authentication
Example:
import (
"crypto/hmac"
"github.com/codesjoy/pkg/utils/xcrypto"
)
key := []byte("32-byte-secret-key-1234567890abcd")
data := []byte("message to authenticate")
// Compute HMAC-SHA256
mac := xcrypto.HMACSHA256(key, data)
// mac is 32 bytes
// Verify later (timing-safe comparison)
expectedMAC := xcrypto.HMACSHA256(key, data)
if hmac.Equal(mac, expectedMAC) {
// Valid - data integrity confirmed
}
API:
HMACSHA256(key []byte, data []byte) []byte- Compute HMAC-SHA256 hash
Security Best Practices:
- Use cryptographically secure random key generators (crypto/rand)
- Key length should be at least 32 bytes (256 bits)
- Never hardcode keys in source code
- Always use
hmac.Equal()for timing-safe verification - Rotate keys periodically in production
cookie - HTTP Cookie Utilities
Parse and format HTTP Cookie headers with proper error handling.
Use Cases:
- Web servers and middleware
- Proxy development
- Cookie extraction and validation
- HTTP header manipulation
Example:
import "github.com/codesjoy/pkg/utils/cookie"
// Extract a specific cookie from raw Cookie header
rawHeader := "session=abc123; user=john; theme=dark"
c, err := cookie.GetCookie(rawHeader, "session")
if err != nil {
// Handle malformed cookie
}
// c.Name = "session", c.Value = "abc123"
// Parse all cookies
cookies := cookie.Parse(rawHeader)
// Returns []*http.Cookie{{Name: "session", Value: "abc123"}, ...}
// Format cookies back to strings
formatted := cookie.Format(cookies)
// Returns []string{"session=abc123", "user=john", "theme=dark"}
API:
GetCookie(rawCookies, name string) (*http.Cookie, error)- Extract cookie by nameParse(rawCookies string) []*http.Cookie- Parse all cookies from headerFormat(cookies []*http.Cookie) []string- Convert cookies to string format
Behavior:
GetCookiereturnsnil, nilwhen cookie is not foundGetCookiereturns error when header contains malformed fragmentsParseskips invalid fragments silently (does not expose errors)
xemail - Email Validation
Validate email address syntax using RFC-compliant pattern matching.
Use Cases:
- Form validation
- User registration
- Email input verification
- Data cleaning
Example:
import "github.com/codesjoy/pkg/utils/xemail"
// Validate email addresses
xemail.IsValidEmail("user@example.com") // true
xemail.IsValidEmail("user.name@example.co.uk") // true
xemail.IsValidEmail("invalid") // false
xemail.IsValidEmail("user@") // false
xemail.IsValidEmail("@example.com") // false
API:
IsValidEmail(email string) bool- Check if email has valid syntax
Note: This validates syntax only (ASCII-focused), not mailbox deliverability. Use SMTP verification for deliverability checks.
xgo - Panic-Safe Goroutines
Execute goroutines with automatic panic recovery and logging.
Use Cases:
- Background workers
- Concurrent task processing
- Long-running services
- Panic-safe async operations
Example:
import (
"context"
"log/slog"
"github.com/codesjoy/pkg/utils/xgo"
)
// Simple panic-safe goroutine
xgo.Go(func() {
// This code runs in a goroutine
// Panics are caught and logged automatically
})
// With context propagation
ctx := context.Background()
xgo.GoWithCtx(ctx, func(ctx context.Context) {
// Context is available here
// Panics are caught and logged with context
})
// Custom panic handler
runner := xgo.New(
xgo.WithLogger(slog.Default()),
xgo.WithPanicHandler(func(info xgo.PanicInfo) {
// Custom panic handling
// info.Recovered - panic value
// info.Stack - stack trace
// info.Ctx - context if available
}),
)
runner.Go(func() {
// Custom panic handling applies
})
API:
Go(f func())- Run function in goroutine with panic recoveryGoWithCtx(ctx context.Context, f func(context.Context))- Run with contextNew(opts ...Option) *Runner- Create custom runner with options
Options:
WithLogger(logger *slog.Logger)- Set panic logger (nil to disable)WithPanicHandler(handler PanicHandler)- Set custom panic callback
Default Behavior:
- Panics are logged using
log/slog - Stack traces are captured and logged
- Context values are preserved in panic info
xmap - Map Utilities
Operate on dynamic map structures with deep merge, recursive key normalization, and path lookup.
Use Cases:
- Merge layered configuration maps (defaults + user + env)
- Normalize decoded YAML-like structures (
map[interface{}]interface{}) to string-key maps - Read nested fields from untyped payloads
Example:
import "github.com/codesjoy/pkg/utils/xmap"
defaults := map[string]interface{}{
"server": map[string]interface{}{"host": "0.0.0.0", "port": 8080},
}
override := map[string]interface{}{
"server": map[string]interface{}{"port": 9000},
}
xmap.MergeStringMap(defaults, override)
// defaults["server"].(map[string]interface{})["port"] == 9000
raw := map[string]interface{}{
"config": map[interface{}]interface{}{
"region": "us-east-1",
},
}
xmap.CoverInterfaceMapToStringMap(raw)
// raw["config"] is map[string]interface{}{"region": "us-east-1"}
value := xmap.DeepSearchInMap(raw, "config", "region")
// value == "us-east-1"
API:
MergeStringMap(dst map[string]interface{}, src ...map[string]interface{})- Recursively merge source maps into destinationToMapStringInterface(src map[interface{}]interface{}) map[string]interface{}- Convert interface-key map to string-key mapCoverInterfaceMapToStringMap(src map[string]interface{})- Recursively normalize nested map/slice structuresDeepSearchInMap(m map[string]interface{}, paths ...string) interface{}- Query nested value by path
Behavior:
- Type mismatch in
MergeStringMapis ignored (source value is not applied) DeepSearchInMapreturnsnilwhen path is missing or intermediate node is not a map
xnet - Network Utilities
Provide policy-oriented helpers for local address discovery and safe random TCP listening.
Use Cases:
- Pick a preferred local IP address (private-first or public-first)
- Enumerate local IPv4/IPv6 addresses with stable ordering
- Bind random TCP ports without TOCTOU race between lookup and listen
Example:
import (
"context"
"log"
"github.com/codesjoy/pkg/utils/xnet"
)
ctx := context.Background()
// Select one local address (default policy: private-first, includes CGNAT)
selected, err := xnet.SelectLocalAddr(ctx, xnet.LocalAddrOptions{
Family: xnet.FamilyAny,
})
if err != nil {
log.Fatal(err)
}
log.Printf("selected local ip: %s", selected)
// List local addresses (stable, deduplicated, sorted)
all, err := xnet.ListLocalAddrs(ctx, xnet.LocalAddrOptions{
IncludeLoopback: true,
IncludeLinkLocal: true,
})
if err != nil {
log.Fatal(err)
}
log.Printf("local addrs: %v", all)
// Listen on a random tcp4 port safely and keep listener open
ln, addrPort, err := xnet.ListenTCPRandom(ctx, xnet.ListenOptions{Network: "tcp4"})
if err != nil {
log.Fatal(err)
}
defer ln.Close()
log.Printf("listening on %s", addrPort)
API:
ListLocalAddrs(ctx context.Context, opts LocalAddrOptions) ([]netip.Addr, error)- List filtered, deduplicated, sorted local addressesSelectLocalAddr(ctx context.Context, opts LocalAddrOptions) (netip.Addr, error)- Select one local address by policyListenTCPRandom(ctx context.Context, opts ListenOptions) (net.Listener, netip.AddrPort, error)- Listen on random TCP port and return open listener
Types:
Family/FamilyAny/FamilyIPv4/FamilyIPv6- Address family controlsLocalAddrOptions- Selection/filter behavior (public/private preference, CGNAT, loopback, link-local)ListenOptions- Network/host controls for random TCP listen
Errors:
ErrNoUsableAddress- No address matches the requested selection policy
xsync - Concurrency Primitives
Provide reusable concurrency primitives built on top of the standard library.
Use Cases:
- One-time event signaling across goroutines
- Unbounded FIFO queue for producer/consumer workflows
- Serial callback execution with panic containment and graceful shutdown
Example:
import (
"context"
"log"
"github.com/codesjoy/pkg/utils/xsync"
)
ctx := context.Background()
// Event
evt := xsync.NewEvent()
go func() {
// do work...
evt.Fire()
}()
if err := evt.Wait(ctx); err != nil {
log.Fatal(err)
}
// Unbounded queue
q := xsync.NewUnbounded[int]()
_ = q.Put(1)
_ = q.Put(2)
q.Close()
for {
v, ok := q.Get()
if !ok {
break
}
log.Printf("queue value=%d", v)
}
// Serializer
s := xsync.NewSerializer(ctx)
defer s.Close()
_ = s.Submit(func(context.Context) { log.Println("task 1") })
_ = s.Submit(func(context.Context) { log.Println("task 2") })
API:
NewEvent() *Event(*Event).Fire() bool(*Event).Done() <-chan struct{}(*Event).HasFired() bool(*Event).Wait(ctx context.Context) errorNewUnbounded[T any]() *Unbounded[T](*Unbounded[T]).Put(v T) error(*Unbounded[T]).Get() (T, bool)(*Unbounded[T]).TryGet() (T, bool)(*Unbounded[T]).Close()(*Unbounded[T]).Len() intNewSerializer(ctx context.Context) *Serializer(*Serializer).Submit(fn func(context.Context)) error(*Serializer).Close()(*Serializer).Done() <-chan struct{}
Errors:
ErrQueueClosed- Queue is closed and cannot accept new itemsErrSerializerClosed- Serializer is closed or unavailable
Testing
Run tests for all packages:
# Run all tests
cd utils && go test ./...
# Run with coverage
go test -cover ./...
# Run benchmarks
go test -bench=. -benchmem ./...
# Race detection
go test -race ./...
Run tests for a specific package:
# Test single package
go test ./base62
go test ./xcrypto
go test ./cookie
go test ./xemail
go test ./xgo
go test ./xmap
go test ./xnet
go test ./xsync
Module Structure
utils/
├── base62/ # Base62 encoding/decoding
│ ├── base62.go
│ └── base62_test.go
├── xcrypto/ # Cryptographic functions
│ ├── crypto.go
│ └── crypto_test.go
├── cookie/ # HTTP cookie utilities
│ ├── cookie.go
│ └── cookie_test.go
├── xemail/ # Email validation
│ ├── email.go
│ └── email_test.go
├── xgo/ # Panic-safe goroutines
│ ├── goroutine.go
│ └── goroutine_test.go
├── xmap/ # Map utilities
│ ├── xmap.go
│ └── xmap_test.go
├── xnet/ # Network utilities
│ ├── net.go
│ └── net_test.go
├── xsync/ # Concurrency primitives
│ ├── callback_serializer.go
│ ├── callback_serializer_test.go
│ ├── event.go
│ ├── event_test.go
│ ├── unbounded.go
│ └── unbounded_test.go
├── go.mod
└── README.md
Dependencies
- Go Version: 1.25+
- External Dependencies: None (standard library only)
Performance
All packages are optimized for performance:
- base62: Efficient encoding/decoding with precomputed lookup tables
- xcrypto: Direct crypto/hmac and crypto/sha256 usage
- cookie: Zero-allocation parsing where possible
- xemail: Precompiled regex pattern
- xgo: Minimal overhead panic recovery
- xmap: Recursive merge and map normalization helpers
- xnet: netip-based filtering and safe random listen helpers
- xsync: Reusable event/queue/serializer concurrency primitives
Benchmark results on typical hardware:
BenchmarkEncodeInt64-8 100000000 10.2 ns/op
BenchmarkDecodeInt64-8 100000000 12.5 ns/op
BenchmarkHMACSHA256-8 5000000 285 ns/op
BenchmarkGetCookie_Hit-8 30000000 45.2 ns/op
BenchmarkParse-8 10000000 156 ns/op
Best Practices
-
base62
- Always check for errors when encoding/decoding
- Use for URL-safe IDs, not for security (encoding is reversible)
-
xcrypto
- Use timing-safe comparison (
hmac.Equal) for verification - Generate keys with
crypto/rand, never hardcode - Minimum 32-byte keys for HMAC-SHA256
- Use timing-safe comparison (
-
cookie
- Handle
ErrInvalidCookieHeaderwhen usingGetCookie - Use
Parsefor lenient parsing,GetCookiefor strict validation
- Handle
-
xemail
- Validates syntax only, not deliverability
- For production, combine with SMTP verification
-
xgo
- Always use panic-safe goroutines in production
- Set up custom panic handlers for critical services
- Preserve context for tracing and cancellation
-
xmap
- Normalize external/untyped map payloads before deep access
- Use
MergeStringMapfor layered config merge with deterministic type behavior - Use
DeepSearchInMapfor optional nested field reads
-
xnet
- Prefer
SelectLocalAddrover ad-hoc interface scans in app code - Keep default private-first policy unless explicit public-first requirement exists
- Keep the returned listener from
ListenTCPRandomopen to avoid port races
- Prefer
-
xsync
- Use
Eventfor one-time broadcast signaling between goroutines - Use
Unbounded[T]when producer throughput must not block on channel capacity - Use
Serializerto run callbacks in FIFO order and isolate callback panics
- Use
License
Copyright 2022 The codesjoy Authors.
Licensed under the Apache License, Version 2.0.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package base62 provides standard base62 encoding and decoding for int64 values.
|
Package base62 provides standard base62 encoding and decoding for int64 values. |
|
Package cookie provides helpers for parsing and formatting HTTP Cookie headers.
|
Package cookie provides helpers for parsing and formatting HTTP Cookie headers. |
|
Package xcrypto provides cryptographic functions for HMAC-SHA256 operations.
|
Package xcrypto provides cryptographic functions for HMAC-SHA256 operations. |
|
Package xemail validates email address format.
|
Package xemail validates email address format. |
|
Package xgo provides panic-safe goroutine helpers.
|
Package xgo provides panic-safe goroutine helpers. |
|
Package xmap provides helper functions for map manipulation.
|
Package xmap provides helper functions for map manipulation. |
|
Package xnet provides high-level network helpers on top of Go stdlib.
|
Package xnet provides high-level network helpers on top of Go stdlib. |