### ServiceManager: Coordinated Service Lifecycle Management Source: https://context7.com/ordishs/go-utils/llms.txt Demonstrates initializing, starting, and stopping multiple services concurrently using ServiceManager. Services implement the `Service` interface. OS signals trigger graceful shutdown. ```go package main import ( "context" "fmt" "time" "github.com/ordishs/go-utils/servicemanager" ) // HTTPService implements servicemanager.Service type HTTPService struct{ addr string } func (s *HTTPService) Init(ctx context.Context) error { fmt.Printf("HTTP: init on %s\n", s.addr) return nil } func (s *HTTPService) Start(ctx context.Context) error { fmt.Println("HTTP: started") <-ctx.Done() // block until context cancelled return nil } func (s *HTTPService) Stop(ctx context.Context) error { fmt.Println("HTTP: stopped") return nil } // WorkerService implements servicemanager.Service type WorkerService struct{} func (w *WorkerService) Init(ctx context.Context) error { return nil } func (w *WorkerService) Start(ctx context.Context) error { fmt.Println("Worker: started") select { case <-ctx.Done(): return nil case <-time.After(5 * time.Second): return fmt.Errorf("worker timeout") } } func (w *WorkerService) Stop(ctx context.Context) error { fmt.Println("Worker: stopped") return nil } func main() { sm := servicemanager.NewServiceManager() sm.AddService("HTTP", &HTTPService{addr: ":8080"}) sm.AddService("Worker", &WorkerService{}) ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() if err := sm.StartAllAndWait(ctx); err != nil { fmt.Println("error:", err) } // HTTP: init on :8080 // HTTP: started // Worker: started // Worker: stopped ← reverse order on shutdown // HTTP: stopped } ``` -------------------------------- ### Create and Use Safemap for Concurrency-Safe Maps Source: https://context7.com/ordishs/go-utils/llms.txt Shows how to create a concurrency-safe map using `safemap.New` and perform common operations like Get, Set, Has, Delete, and iteration. This map protects against race conditions. ```go package main import ( "fmt" "github.com/ordishs/go-utils/safemap" ) func main() { sm := safemap.New[string, int]() sm.Set("requests", 0) sm.Set("errors", 0) sm.Set("latency_ms", 250) if v, ok := sm.Get("latency_ms"); ok { fmt.Println("latency:", v) // latency: 250 } fmt.Println("has errors:", sm.Has("errors")) // has errors: true fmt.Println("len:", sm.Len()) // len: 3 sm.Each(func(k string, v int) { fmt.Printf(" %s = %d\n", k, v) }) sm.Delete("errors") fmt.Println("keys after delete:", sm.Keys()) // keys after delete: [requests latency_ms] } ``` -------------------------------- ### Safemap - New Source: https://context7.com/ordishs/go-utils/llms.txt Creates a new concurrency-safe map. Provides methods for Get, Set, Delete, Has, Keys, Values, Each, and EachWithBreak. ```APIDOC ## Safemap - New ### Description Creates a concurrency-safe map with methods for Get, Set, Delete, Has, Keys, Values, Each, and EachWithBreak. ### Method Signature `safemap.New[K comparable, V any]() *SafeMap[K, V]` ### Parameters None ### Usage Example ```go package main import ( "fmt" "github.com/ordishs/go-utils/safemap" ) func main() { sm := safemap.New[string, int]() sm.Set("requests", 0) sm.Set("errors", 0) sm.Set("latency_ms", 250) if v, ok := sm.Get("latency_ms"); ok { fmt.Println("latency:", v) // latency: 250 } fmt.Println("has errors:", sm.Has("errors")) // has errors: true fmt.Println("len:", sm.Len()) // len: 3 sm.Each(func(k string, v int) { fmt.Printf(" %s = %d\n", k, v) }) sm.Delete("errors") fmt.Println("keys after delete:", sm.Keys()) // keys after delete: [requests latency_ms] } ``` ``` -------------------------------- ### Implement Two-Lock Concurrent Queue with WaitGroup Source: https://context7.com/ordishs/go-utils/llms.txt Utilizes a two-lock concurrent queue (`CQueue`) for higher throughput with separate head and tail mutexes. This example shows concurrent producers and consumers. ```go package main import ( "fmt" "sync" "github.com/ordishs/go-utils/lockfree" ) func main() { q := lockfree.NewCQueue[string]() var wg sync.WaitGroup // 3 concurrent producers for _, msg := range []string{"a", "b", "c"} { wg.Add(1) go func(m string) { defer wg.Done() q.Enqueue(m) }(msg) } wg.Wait() for { v, ok := q.DequeueAsType() if !ok { break } fmt.Println(v) } } ``` -------------------------------- ### Lockfree Queue - NewQueue Source: https://context7.com/ordishs/go-utils/llms.txt Implements Michael & Scott's non-blocking queue using atomic compare-and-swap. Use DequeueAsType to get the value already typed. ```APIDOC ## Lockfree Queue - NewQueue ### Description Implements Michael & Scott's non-blocking queue using atomic compare-and-swap. Use `DequeueAsType` to get the value already typed. ### Method Signature `lockfree.NewQueue[T any]() *Queue[T]` ### Parameters None ### Usage Example ```go package main import ( "fmt" "github.com/ordishs/go-utils/lockfree" ) func main() { q := lockfree.NewQueue[int]() q.Enqueue(10) q.Enqueue(20) q.Enqueue(30) for { v, ok := q.DequeueAsType() if !ok { break } fmt.Println(v) // 10, 20, 30 } } ``` ``` -------------------------------- ### GetGRPCClient and GetGRPCServer with ConnectionOptions Source: https://context7.com/ordishs/go-utils/llms.txt Demonstrates setting up a gRPC client with insecure transport, Prometheus metrics, OpenTelemetry tracing, and retry logic. Also shows setting up a gRPC server with mutual TLS, certificate files, and message size limits. ```go package main import ( "context" "fmt" utils "github.com/ordishs/go-utils" ) func main() { ctx := context.Background() // --- gRPC CLIENT --- clientConn, err := utils.GetGRPCClient(ctx, "dns:///my-service:50051", &utils.ConnectionOptions{ SecurityLevel: 0, // insecure Prometheus: true, // enable Prometheus client metrics OpenTelemetry: true, // enable OTel tracing MaxRetries: 3, // retry transient errors RetryBackoff: 100e6, // 100 ms in nanoseconds (time.Duration) Credentials: utils.NewPassCredentials(map[string]string{ "authorization": "Bearer my-token", }), }) if err != nil { panic(err) } defer clientConn.Close() fmt.Println("client connected:", clientConn.Target()) // --- gRPC SERVER with mutual TLS --- server, err := utils.GetGRPCServer(&utils.ConnectionOptions{ SecurityLevel: 2, // mutual TLS CertFile: "/certs/server.crt", KeyFile: "/certs/server.key", CaCertFile: "/certs/ca.crt", Prometheus: true, MaxMessageSize: 64 * 1024 * 1024, // 64 MiB }) if err != nil { panic(err) } _ = server // register your protobuf services here, then server.Serve(listener) fmt.Println("server created") } ``` -------------------------------- ### Implement Slice-Backed Concurrent Queue with Capacity Hint Source: https://context7.com/ordishs/go-utils/llms.txt Demonstrates a simpler slice-backed concurrent queue (`SliceQueue`) that uses mutexes. Providing an initial capacity hint can optimize performance by reducing reallocations. ```go package main import ( "fmt" "github.com/ordishs/go-utils/lockfree" ) func main() { q := lockfree.NewSliceQueue[float64](16) // pre-allocate capacity 16 q.Enqueue(1.1) q.Enqueue(2.2) q.Enqueue(3.3) for { v, ok := q.DequeueAsType() if !ok { break } fmt.Printf("%.1f\n", v) // 1.1, 2.2, 3.3 } } ``` -------------------------------- ### GetGRPCServer Source: https://context7.com/ordishs/go-utils/llms.txt Creates a gRPC server instance with options for security, message size, and observability. ```APIDOC ## GetGRPCServer ### Description Creates a gRPC server with optional TLS (including mutual TLS), Prometheus metrics, and OpenTelemetry tracing. ### Method `GetGRPCServer(options *ConnectionOptions) (*grpc.Server, error)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go server, err := utils.GetGRPCServer(&utils.ConnectionOptions{ SecurityLevel: 2, // mutual TLS CertFile: "/certs/server.crt", KeyFile: "/certs/server.key", CaCertFile: "/certs/ca.crt", Prometheus: true, MaxMessageSize: 64 * 1024 * 1024, // 64 MiB }) if err != nil { panic(err) } // register your protobuf services here, then server.Serve(listener) ``` ### Response #### Success Response (200) - `*grpc.Server` (grpc.Server) - A configured gRPC server instance. - `error` (error) - An error if the server creation fails. #### Response Example ```go // server created ``` ``` -------------------------------- ### Create and Use ExpiringMap with Eviction Channel Source: https://context7.com/ordishs/go-utils/llms.txt Demonstrates creating a generic map with a time-to-live (TTL) for entries and observing evicted items via a channel. Entries are automatically removed after the specified duration. ```go package main import ( "fmt" "time" "github.com/ordishs/go-utils/expiringmap" ) func main() { evicted := make(chan []string, 10) m := expiringmap.New[string, string](200*time.Millisecond). WithEvictionChannel(evicted) m.Set("session:1", "user-alice") m.Set("session:2", "user-bob") if v, ok := m.Get("session:1"); ok { fmt.Println("found:", v) // found: user-alice } time.Sleep(300*time.Millisecond) // entries expire if _, ok := m.Get("session:1"); !ok { fmt.Println("expired") // expired } evictedItems := <-evicted fmt.Println("evicted count:", len(evictedItems)) // evicted count: 2 // Iterate non-expired entries m.Set("session:3", "user-carol") m.IterateWithFn(func(k, v string) bool { fmt.Printf(" %s → %s\n", k, v) return true // continue }) } ``` -------------------------------- ### Discover Public and Local IP Addresses Source: https://context7.com/ordishs/go-utils/llms.txt GetPublicIPAddress races OpenDNS lookup and an HTTP call to ifconfig.co, returning the first successful resolution. GetIPAddressesWithHint finds local non-loopback IPv4 addresses matching a provided regex. ```go package main import ( "fmt" utils "github.com/ordishs/go-utils" ) func main() { // Public IP (races two resolvers with 15 s timeout) ip, err := utils.GetPublicIPAddress() if err != nil { panic(err) } fmt.Println("Public IP:", ip) // Public IP: 203.0.113.42 // Local interfaces matching "192.168.*" addrs, err := utils.GetIPAddressesWithHint(`^192\.168\.`) if err != nil { panic(err) } fmt.Println("Local IPs:", addrs) // Local IPs: [192.168.1.10] } ``` -------------------------------- ### Implement Lock-Free Queue with Enqueue and Dequeue Source: https://context7.com/ordishs/go-utils/llms.txt Demonstrates the usage of a lock-free unbounded FIFO queue implemented using atomic compare-and-swap operations. Use `DequeueAsType` for type-safe retrieval. ```go package main import ( "fmt" "github.com/ordishs/go-utils/lockfree" ) func main() { q := lockfree.NewQueue[int]() q.Enqueue(10) q.Enqueue(20) q.Enqueue(30) for { v, ok := q.DequeueAsType() if !ok { break } fmt.Println(v) // 10, 20, 30 } } ``` -------------------------------- ### GetGRPCClient Source: https://context7.com/ordishs/go-utils/llms.txt Establishes a gRPC client connection with configurable options for security, observability, and retries. ```APIDOC ## GetGRPCClient ### Description Creates a gRPC client connection to a specified address with optional TLS, Prometheus metrics, OpenTelemetry tracing, and retry logic. ### Method `GetGRPCClient(ctx context.Context, address string, options *ConnectionOptions) (*grpc.ClientConn, error)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go clientConn, err := utils.GetGRPCClient(ctx, "dns:///my-service:50051", &utils.ConnectionOptions{ SecurityLevel: 0, // insecure Prometheus: true, // enable Prometheus client metrics OpenTelemetry: true, // enable OTel tracing MaxRetries: 3, // retry transient errors RetryBackoff: 100e6, // 100 ms in nanoseconds (time.Duration) Credentials: utils.NewPassCredentials(map[string]string{ "authorization": "Bearer my-token", }), }) if err != nil { panic(err) } defer clientConn.Close() ``` ### Response #### Success Response (200) - `*grpc.ClientConn` (grpc.ClientConn) - A connected gRPC client connection. - `error` (error) - An error if the connection fails. #### Response Example ```go // client connected: dns:///my-service:50051 ``` ``` -------------------------------- ### Calculate Median Time Past (Bitcoin Consensus) Source: https://context7.com/ordishs/go-utils/llms.txt Accepts up to 11 Unix timestamps and returns the median as a time.Time, matching Bitcoin's Median Time Past rule. Providing more than 11 timestamps will result in an error. ```go package main import ( "fmt" utils "github.com/ordishs/go-utils" ) func main() { // Last 11 block timestamps (Unix seconds) timestamps := []int{ 1700000000, 1700000060, 1700000120, 1700000180, 1700000240, 1700000300, 1700000360, 1700000420, 1700000480, 1700000540, 1700000600, } medianTime, err := utils.CalcPastMedianTime(timestamps) if err != nil { panic(err) } fmt.Println("Median time:", medianTime) // Median time: 2023-11-14 22:13:20 +0000 UTC // Too many timestamps → error too := make([]int, 12) _, err = utils.CalcPastMedianTime(too) fmt.Println(err) // too many timestamps for median time calculation - got 12, max 11 } ``` -------------------------------- ### Pluggable Structured Logging Interface Source: https://context7.com/ordishs/go-utils/llms.txt The Logger interface provides Debugf, Infof, Warnf, Errorf, and Fatalf methods. A custom implementation can be passed to library functions to redirect logs to any backend. ```go package main import ( "fmt" utils "github.com/ordishs/go-utils" ) type myLogger struct{} func (myLogger) LogLevel() int { return 0 } func (myLogger) Debugf(f string, a ...interface{}) { fmt.Printf("[DEBUG] "+f+"\n", a...) } func (myLogger) Infof(f string, a ...interface{}) { fmt.Printf("[INFO] "+f+"\n", a...) } func (myLogger) Warnf(f string, a ...interface{}) { fmt.Printf("[WARN] "+f+"\n", a...) } func (myLogger) Errorf(f string, a ...interface{}) { fmt.Printf("[ERROR] "+f+"\n", a...) } func (myLogger) Fatalf(f string, a ...interface{}) { fmt.Printf("[FATAL] "+f+"\n", a...) } func main() { var logger utils.Logger = myLogger{} // Pass custom logger to DisableCanonicalMode state := utils.DisableCanonicalMode(logger) utils.RestoreTTY(state) } ``` -------------------------------- ### batcher.New Source: https://context7.com/ordishs/go-utils/llms.txt Creates a new batch processor that accumulates items and processes them based on size or timeout. ```APIDOC ## Batcher ### Description Creates a generic worker that accumulates items and calls the provided function when either the batch reaches `size` items or `timeout` elapses. Set `background=true` to invoke the callback in a new goroutine. ### Parameters * `size` (int) - The maximum number of items in a batch. * `timeout` (time.Duration) - The maximum time to wait before processing a batch. * `callback` (func([]*T)) - The function to call with the processed batch. * `background` (bool) - If true, the callback is invoked in a new goroutine. ### Returns * `*batcher.Batcher[T]` - A pointer to the created batcher. ### Example ```go package main import ( "fmt" "time" "github.com/ordishs/go-utils/batcher" ) func main() { // Process in batches of 3 or every 500 ms, whichever comes first b := batcher.New[string](3, 500*time.Millisecond, func(batch []*string) { fmt.Printf("Processing batch of %d: ", len(batch)) for _, s := range batch { fmt.Printf("%s ", *s) } fmt.Println() }, false) items := []string{"alpha", "beta", "gamma", "delta", "epsilon"} for i := range items { b.Put(&items[i]) } time.Sleep(600 * time.Millisecond) // wait for timeout flush } ``` ``` -------------------------------- ### AtomicStat: Concurrent Duration Accumulator Source: https://context7.com/ordishs/go-utils/llms.txt Tracks a count and total duration for measuring operation latency. Use `AddTime` to record durations. Provides average calculations. ```go package main import ( "fmt" "time" "github.com/ordishs/go-utils/stat" ) func processItem(s *stat.AtomicStat) { start := time.Now() time.Sleep(10 * time.Millisecond) // simulated work s.AddTime(start) } func main() { s := stat.NewAtomicStat() for i := 0; i < 5; i++ { processItem(s) } fmt.Println("count:", s.GetCount()) // count: 5 fmt.Println("average:", s.GetAverageString()) // average: ~10ms fmt.Println(s.String()) // 5 (10ms) } ``` -------------------------------- ### SafeClose: Close Channel Without Panicking on Double-Close Source: https://context7.com/ordishs/go-utils/llms.txt Safely close a channel, silently recovering from panics that occur if the channel is already closed. ```Go package main import ( utils "github.com/ordishs/go-utils" ) func main() { ch := make(chan string, 2) ch <- "a" utils.SafeClose(ch) // closes normally utils.SafeClose(ch) // would panic without SafeClose — recovered silently } ``` -------------------------------- ### GetPublicIPAddress / GetIPAddressesWithHint Source: https://context7.com/ordishs/go-utils/llms.txt Discovers IP addresses. GetPublicIPAddress finds the public IP by racing DNS and HTTP lookups. GetIPAddressesWithHint finds local IPv4 addresses matching a regex. ```APIDOC ## GetPublicIPAddress ### Description Races OpenDNS lookup and an HTTP call to `ifconfig.co`, returning whichever resolves first. ### Returns * `string` - The public IP address. * `error` - An error if the IP address cannot be determined. ### Example ```go package main import ( "fmt" utils "github.com/ordishs/go-utils" ) func main() { ip, err := utils.GetPublicIPAddress() if err != nil { panic(err) } fmt.Println("Public IP:", ip) } ``` ## GetIPAddressesWithHint ### Description Returns all local non-loopback IPv4 addresses matching a provided regular expression. ### Parameters * `hintRegex` (string) - A regular expression to filter IP addresses. ### Returns * `[]string` - A slice of matching IP addresses. * `error` - An error if IP addresses cannot be retrieved or filtered. ### Example ```go package main import ( "fmt" utils "github.com/ordishs/go-utils" ) func main() { addrs, err := utils.GetIPAddressesWithHint(`^192\.168\.`) // Example: Match IPs starting with 192.168. if err != nil { panic(err) } fmt.Println("Local IPs:", addrs) } ``` ``` -------------------------------- ### AtomicStats: Named Multi-Operation Statistics Source: https://context7.com/ordishs/go-utils/llms.txt Groups multiple `AtomicStat` entries by string key for aggregating totals and printing a formatted summary table. Use `AddDuration` to record durations for specific operations. ```go package main import ( "fmt" "time" "github.com/ordishs/go-utils/stat" ) func main() { stats := stat.NewAtomicStats() // Record durations for different operations for i := 0; i < 3; i++ { stats.AddDuration("db.query", 15*time.Millisecond) stats.AddDuration("cache.get", 2*time.Millisecond) stats.AddDuration("http.call", 50*time.Millisecond) } fmt.Println("total count:", stats.GetCount()) // total count: 9 avgDur := stats.GetAverageDuration() fmt.Println("overall avg:", avgDur) // Formatted table output fmt.Print(stats.String(" ")) // cache.get: 3 (2ms) // db.query: 3 (15ms) // http.call: 3 (50ms) // TOTAL: 9 (22ms) } ``` -------------------------------- ### Format Time as ISO 8601 Source: https://context7.com/ordishs/go-utils/llms.txt Formats a time.Time value into a string adhering to the ISO 8601 standard format: "2006-01-02T15:04:05.000Z". ```go package main import ( "fmt" "time" utils "github.com/ordishs/go-utils" ) func main() { t := time.Date(2024, 6, 15, 12, 30, 45, 123000000, time.UTC) fmt.Println(utils.ISOFormat(t)) // 2024-06-15T12:30:45.123Z } ``` -------------------------------- ### Batch Processor with Size or Timeout Trigger Source: https://context7.com/ordishs/go-utils/llms.txt Creates a worker that accumulates items and calls a provided function when the batch reaches a specified size or a timeout elapses. Set background=true to invoke the callback in a new goroutine. ```go package main import ( "fmt" "time" "github.com/ordishs/go-utils/batcher" ) func main() { // Process in batches of 3 or every 500 ms, whichever comes first b := batcher.New[string](3, 500*time.Millisecond, func(batch []*string) { fmt.Printf("Processing batch of %d: ", len(batch)) for _, s := range batch { fmt.Printf("%s ", *s) } fmt.Println() }, false) items := []string{"alpha", "beta", "gamma", "delta", "epsilon"} for i := range items { b.Put(&items[i]) } time.Sleep(600 * time.Millisecond) // wait for timeout flush // Output: // Processing batch of 3: alpha beta gamma // Processing batch of 2: delta epsilon } ``` -------------------------------- ### ReverseSlice / ReverseHash: In-Place and Copy Reversal of Slices and Hashes Source: https://context7.com/ordishs/go-utils/llms.txt Reverses byte slices or 32-byte arrays. Includes convenience wrappers for Bitcoin little-endian hex encoding/decoding. ```Go package main import ( "fmt" utils "github.com/ordishs/go-utils" ) func main() { // Reverse a copy original := []int{1, 2, 3, 4, 5} reversed := utils.ReverseSlice(original) fmt.Println(reversed) // [5 4 3 2 1] fmt.Println(original) // [1 2 3 4 5] — unchanged // Reverse in place utils.ReverseSliceInPlace(original) fmt.Println(original) // [5 4 3 2 1] // Decode a Bitcoin txid hex string (big-endian) → little-endian bytes txidHex := "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" b, err := utils.DecodeAndReverseHexString(txidHex) if err != nil { panic(err) } fmt.Printf("%x\n", b) // bytes in little-endian order // Re-encode little-endian bytes back to big-endian hex reEncoded := utils.ReverseAndHexEncodeSlice(b) fmt.Println(reEncoded == txidHex) // true } ``` -------------------------------- ### Pair: Generic Two-Value Tuple for Returning Related Values Source: https://context7.com/ordishs/go-utils/llms.txt A generic, typed, and printable two-element container. Useful for returning or passing two related values without defining a dedicated struct. ```Go package main import ( "fmt" utils "github.com/ordishs/go-utils" ) func divide(a, b float64) utils.Pair[float64, error] { if b == 0 { return utils.NewPair[float64, error](0, fmt.Errorf("division by zero")) } return utils.NewPair[float64, error](a/b, nil) } func main() { result := divide(10, 3) fmt.Println(result) // [3.3333333333333335, ] fmt.Println(result.First) // 3.3333333333333335 bad := divide(5, 0) fmt.Println(bad.Second) // division by zero } ``` -------------------------------- ### CalcPastMedianTime Source: https://context7.com/ordishs/go-utils/llms.txt Calculates the median block timestamp according to Bitcoin's Median Time Past rule, accepting up to 11 Unix timestamps and returning a time.Time object. ```APIDOC ## CalcPastMedianTime ### Description Accepts up to 11 Unix timestamps (integers) and returns the median as a `time.Time`, matching Bitcoin's Median Time Past rule. ### Parameters * `timestamps` ([]int) - A slice of Unix timestamps. ### Returns * `time.Time` - The calculated median time. * `error` - An error if the number of timestamps is invalid. ### Example ```go package main import ( "fmt" utils "github.com/ordishs/go-utils" ) func main() { timestamps := []int{ 1700000000, 1700000060, 1700000120, 1700000180, 1700000240, 1700000300, 1700000360, 1700000420, 1700000480, 1700000540, 1700000600, } medianTime, err := utils.CalcPastMedianTime(timestamps) if err != nil { panic(err) } fmt.Println("Median time:", medianTime) } ``` ``` -------------------------------- ### SafeSend: Send to Channel Without Panicking on Closed Channels Source: https://context7.com/ordishs/go-utils/llms.txt Safely send a value to a channel, recovering from panics if the channel is closed. Supports an optional timeout for retries on full channels. ```Go package main import ( "fmt" "time" utils "github.com/ordishs/go-utils" ) func main() { ch := make(chan int, 1) // Basic send — returns true on success ok := utils.SafeSend(ch, 42) fmt.Println("sent:", ok) // sent: true // Send to a closed channel — no panic, returns true (recovered) close(ch) ok = utils.SafeSend(ch, 99) fmt.Println("sent to closed:", ok) // sent to closed: true (recovered silently) // Send with retry timeout — retries every 500 ms if channel is full blocked := make(chan string) // unbuffered, nobody reading go func() { time.Sleep(600 * time.Millisecond) fmt.Println(<-blocked) // "hello" }() utils.SafeSend(blocked, "hello", 500*time.Millisecond) } ``` -------------------------------- ### Logger Interface Source: https://context7.com/ordishs/go-utils/llms.txt Defines a pluggable structured logging interface with methods for Debugf, Infof, Warnf, Errorf, and Fatalf. ```APIDOC ## Logger Interface ### Description An interface for pluggable structured logging, providing methods `Debugf`, `Infof`, `Warnf`, `Errorf`, and `Fatalf`. Implement this interface to redirect logs to any backend. ### Methods * `LogLevel() int` * `Debugf(f string, a ...interface{}) * `Infof(f string, a ...interface{}) * `Warnf(f string, a ...interface{}) * `Errorf(f string, a ...interface{}) * `Fatalf(f string, a ...interface{}) ### Example ```go package main import ( "fmt" utils "github.com/ordishs/go-utils" ) type myLogger struct{} func (myLogger) LogLevel() int { return 0 } func (myLogger) Debugf(f string, a ...interface{}) { fmt.Printf("[DEBUG] "+f+"\n", a...) } func (myLogger) Infof(f string, a ...interface{}) { fmt.Printf("[INFO] "+f+"\n", a...) } func (myLogger) Warnf(f string, a ...interface{}) { fmt.Printf("[WARN] "+f+"\n", a...) } func (myLogger) Errorf(f string, a ...interface{}) { fmt.Printf("[ERROR] "+f+"\n", a...) } func (myLogger) Fatalf(f string, a ...interface{}) { fmt.Printf("[FATAL] "+f+"\n", a...) } func main() { var logger utils.Logger = myLogger{} // Pass custom logger to DisableCanonicalMode state := utils.DisableCanonicalMode(logger) utils.RestoreTTY(state) } ``` ``` -------------------------------- ### ReverseSlice / ReverseHash Source: https://context7.com/ordishs/go-utils/llms.txt Functions for reversing byte slices and 32-byte arrays, including helpers for Bitcoin hex encoding. ```APIDOC ## ReverseSlice / ReverseHash ### Description Provides functions to reverse the order of elements in a slice or a fixed-size byte array. Includes specialized functions for handling Bitcoin's little-endian hex encoding. ### Functions - `ReverseSlice[T any](s []T) []T` - Returns a new slice with elements in reverse order. - `ReverseSliceInPlace[T any](s []T)` - Reverses the elements of the slice in place. - `ReverseHash32Bytes(h [32]byte) [32]byte` - Reverses a 32-byte array. - `DecodeAndReverseHexString(s string) ([]byte, error)` - Decodes a hex string (assumed big-endian) into a byte slice in little-endian order. - `ReverseAndHexEncodeSlice(b []byte) string` - Encodes a byte slice (assumed little-endian) into a hex string in big-endian order. ### Parameters - `s` ([]T) - The slice or array to reverse. - `h` ([32]byte) - The 32-byte array to reverse. - `b` ([]byte) - The byte slice to encode. ### Returns - `[]T` - A new slice with reversed elements. - `([]byte, error)` - The decoded byte slice in little-endian order, or an error if decoding fails. - `string` - The hex-encoded string in big-endian order. ``` -------------------------------- ### Lockfree SliceQueue - NewSliceQueue Source: https://context7.com/ordishs/go-utils/llms.txt A slice-backed concurrent queue. Provide an initial capacity hint to avoid early reallocations. ```APIDOC ## Lockfree SliceQueue - NewSliceQueue ### Description A simpler mutex-guarded queue backed by a slice. Provide an initial capacity hint to avoid early reallocations. ### Method Signature `lockfree.NewSliceQueue[T any](capacity int) *SliceQueue[T]` ### Parameters - **capacity** (int) - Required - Initial capacity hint for the underlying slice. ### Usage Example ```go package main import ( "fmt" "github.com/ordishs/go-utils/lockfree" ) func main() { q := lockfree.NewSliceQueue[float64](16) // pre-allocate capacity 16 q.Enqueue(1.1) q.Enqueue(2.2) q.Enqueue(3.3) for { v, ok := q.DequeueAsType() if !ok { break } fmt.Printf("%.1f\n", v) // 1.1, 2.2, 3.3 } } ``` ``` -------------------------------- ### Lockfree CQueue - NewCQueue Source: https://context7.com/ordishs/go-utils/llms.txt Uses separate head and tail mutexes for higher throughput under concurrent producers and consumers. ```APIDOC ## Lockfree CQueue - NewCQueue ### Description Uses separate head and tail mutexes for higher throughput under concurrent producers and consumers. ### Method Signature `lockfree.NewCQueue[T any]() *CQueue[T]` ### Parameters None ### Usage Example ```go package main import ( "fmt" "sync" "github.com/ordishs/go-utils/lockfree" ) func main() { q := lockfree.NewCQueue[string]() var wg sync.WaitGroup // 3 concurrent producers for _, msg := range []string{"a", "b", "c"} { wg.Add(1) go func(m string) { defer wg.Done() q.Enqueue(m) }(msg) } wg.Wait() for { v, ok := q.DequeueAsType() if !ok { break } fmt.Println(v) } } ``` ``` -------------------------------- ### Pair Source: https://context7.com/ordishs/go-utils/llms.txt A generic two-value tuple (container) for returning or passing related values. ```APIDOC ## Pair ### Description A generic container for holding two values of potentially different types. It simplifies returning multiple values from functions without defining a dedicated struct. ### Type Definition `Pair[F, S]` ### Constructor `NewPair[F, S](first F, second S) Pair[F, S]` ### Fields - `First` (F) - The first value in the pair. - `Second` (S) - The second value in the pair. ### Example Usage ```go result := utils.NewPair[float64, error](3.33, nil) fmt.Println(result.First) // 3.33 ``` ``` -------------------------------- ### ExpiringMap - New Source: https://context7.com/ordishs/go-utils/llms.txt Creates a new generic map with a specified TTL duration. Entries are automatically removed after the duration expires. Eviction can be observed via a channel or filtered with a function. ```APIDOC ## New ExpiringMap ### Description Creates a generic map that automatically removes entries after the configured duration. Eviction can be observed via a channel or filtered with a function. ### Method Signature `expiringmap.New[K comparable, V any](ttl time.Duration) *ExpiringMap[K, V]` ### Parameters - **ttl** (time.Duration) - Required - The duration after which entries will expire. ### Optional Configuration - **WithEvictionChannel(evicted chan<- []string)**: Registers a channel to receive evicted keys. ### Usage Example ```go package main import ( "fmt" "time" "github.com/ordishs/go-utils/expiringmap" ) func main() { evicted := make(chan []string, 10) m := expiringmap.New[string, string](200 * time.Millisecond). WithEvictionChannel(evicted) m.Set("session:1", "user-alice") m.Set("session:2", "user-bob") if v, ok := m.Get("session:1"); ok { fmt.Println("found:", v) // found: user-alice } time.Sleep(300 * time.Millisecond) // entries expire if _, ok := m.Get("session:1"); !ok { fmt.Println("expired") // expired } evictedItems := <-evicted fmt.Println("evicted count:", len(evictedItems)) // evicted count: 2 // Iterate non-expired entries m.Set("session:3", "user-carol") m.IterateWithFn(func(k, v string) bool { fmt.Printf(" %s → %s\n", k, v) return true // continue }) } ``` ``` -------------------------------- ### DisableCanonicalMode / RestoreTTY Source: https://context7.com/ordishs/go-utils/llms.txt Manages terminal TTY settings for raw input. DisableCanonicalMode switches to raw mode, and RestoreTTY resets it. ```APIDOC ## DisableCanonicalMode ### Description Switches the terminal to raw mode, allowing characters to be read without requiring the Enter key. ### Parameters * `logger` (utils.Logger, optional) - A custom logger implementation. ### Returns * `interface{}` - A state object to be passed to `RestoreTTY`. ### Example ```go package main import ( "fmt" "os" utils "github.com/ordishs/go-utils" ) func main() { defer utils.RestoreTTY(utils.DisableCanonicalMode()) fmt.Print("Press any key: ") buf := make([]byte, 1) os.Stdin.Read(buf) fmt.Printf("\nYou pressed: %q\n", buf[0]) } ``` ## RestoreTTY ### Description Resets the terminal to its previous TTY state. ### Parameters * `state` (interface{}) - The state object returned by `DisableCanonicalMode`. ### Example ```go package main import ( "fmt" "os" utils "github.com/ordishs/go-utils" ) func main() { state := utils.DisableCanonicalMode() defer utils.RestoreTTY(state) fmt.Print("Press any key: ") buf := make([]byte, 1) os.Stdin.Read(buf) fmt.Printf("\nYou pressed: %q\n", buf[0]) } ``` ``` -------------------------------- ### Control Terminal Canonical Mode for Raw Input Source: https://context7.com/ordishs/go-utils/llms.txt DisableCanonicalMode switches the terminal to raw mode for immediate character input without requiring Enter. Defer RestoreTTY to reset the terminal to its previous state. ```go package main import ( "fmt" "os" utils "github.com/ordishs/go-utils" ) func main() { // Defer restore before disabling defer utils.RestoreTTY(utils.DisableCanonicalMode()) fmt.Print("Press any key: ") buf := make([]byte, 1) os.Stdin.Read(buf) // reads immediately without Enter fmt.Printf("\nYou pressed: %q\n", buf[0]) } ``` -------------------------------- ### SafeClose Source: https://context7.com/ordishs/go-utils/llms.txt Safely closes a channel, recovering from panics if the channel has already been closed. ```APIDOC ## SafeClose ### Description Safely closes a channel, preventing panics if the channel is already closed. This is useful for ensuring that channels are closed exactly once. ### Function Signature `SafeClose(ch chan T)` ### Parameters - `ch` (chan T) - The channel to close. ### Returns None. ``` -------------------------------- ### ISOFormat Source: https://context7.com/ordishs/go-utils/llms.txt Formats a time.Time value into an ISO 8601 string format (YYYY-MM-DDTHH:MM:SS.sssZ). ```APIDOC ## ISOFormat ### Description Returns a time value formatted as `"2006-01-02T15:04:05.000Z"`. ### Parameters * `t` (time.Time) - The time value to format. ### Returns * `string` - The formatted time string. ### Example ```go package main import ( "fmt" "time" utils "github.com/ordishs/go-utils" ) func main() { t := time.Date(2024, 6, 15, 12, 30, 45, 123000000, time.UTC) fmt.Println(utils.ISOFormat(t)) } ``` ``` -------------------------------- ### Sha256d / GetBitcoinHash: Double-SHA256 and Bitcoin Hash Calculation Source: https://context7.com/ordishs/go-utils/llms.txt Computes the double-SHA256 hash of byte data. `GetBitcoinHash` additionally reverses the result to match Bitcoin's display convention. ```Go package main import ( "encoding/hex" "fmt" utils "github.com/ordishs/go-utils" ) func main() { data := []byte("Hello, Bitcoin!") // Raw double-SHA256 hash := utils.Sha256d(data) fmt.Println(hex.EncodeToString(hash)) // Bitcoin-style hash (double-SHA256, reversed) btcHash := utils.GetBitcoinHash(data) fmt.Println(hex.EncodeToString(btcHash)) } ``` -------------------------------- ### Sha256d / GetBitcoinHash Source: https://context7.com/ordishs/go-utils/llms.txt Computes double-SHA256 hashes and provides a Bitcoin-specific hash function. ```APIDOC ## Sha256d / GetBitcoinHash ### Description Implements the double-SHA256 hashing algorithm and a variant tailored for Bitcoin, which reverses the byte order of the final hash. ### Functions - `Sha256d(b []byte) []byte` - Computes `SHA256(SHA256(b))`. - `GetBitcoinHash(b []byte) []byte` - Computes `SHA256(SHA256(b))` and reverses the resulting byte slice. ### Parameters - `b` ([]byte) - The input data to hash. ### Returns - `[]byte` - The resulting hash bytes. ``` -------------------------------- ### SafeSend Source: https://context7.com/ordishs/go-utils/llms.txt Safely sends a value to a channel without panicking if the channel is closed. Supports an optional timeout for retries. ```APIDOC ## SafeSend ### Description Safely sends a value to a channel, recovering from panics if the channel is already closed. An optional timeout can be provided to retry sending if the channel is full. ### Function Signature `SafeSend(ch chan T, value T) bool` `SafeSend(ch chan T, value T, timeout time.Duration) bool` ### Parameters - `ch` (chan T) - The channel to send the value to. - `value` (T) - The value to send. - `timeout` (time.Duration, optional) - The duration to wait before retrying the send if the channel is full. ### Returns - `bool` - `true` if the send was successful or recovered, `false` otherwise (e.g., if timeout occurs without success). ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.