sonirico/vago
{ "createdAt": "2025-05-02T17:32:52Z", "defaultBranch": "main", "description": "A practical Go toolkit with generic utilities for working with slices, maps, and functional programming primitives, streams, databases and more", "fullName": "sonirico/vago", "homepage": "", "language": "Go", "name": "vago", "pushedAt": "2025-09-01T17:04:25Z", "stargazersCount": 93, "topics": [ "functional", "generics", "go", "golang", "maps", "monads", "programming", "slices", "streams", "toolkit", "utils" ], "updatedAt": "2025-10-28T05:36:20Z", "url": "https://github.com/sonirico/vago"}The ultimate toolkit for vaGo developers. A comprehensive collection of functions, data structures, and utilities designed to enhance productivity and code quality with no learning curve and less effort.
📖 View full documentation and examples on pkg.go.dev →
✨ Workspace Architecture
Section titled “✨ Workspace Architecture”This project leverages Go workspaces to provide isolated dependencies for each module. This means:
- 🎯 Lightweight imports: When you import
fporstreams, you won’t download database drivers or logging dependencies - 🔧 Modular design: Each module (
db,lol,num) maintains its owngo.modwith specific dependencies - 📦 Zero bloat: Use only what you need without carrying unnecessary dependencies
- 🚀 Fast builds: Smaller dependency graphs lead to faster compilation and smaller binaries
Example: Importing github.com/sonirico/vago/fp will only pull functional programming utilities, not database connections or logging frameworks.
Modules
Section titled “Modules”Table of Contents
Section titled “Table of Contents”- [🗃️ Db]!(#db) - 6 functions
- [ Ent]!(#ent) - 18 functions
- [🪄 Fp]!(#fp) - 15 functions
- [📝 Lol]!(#lol) - 4 functions
- [🗝️ Maps]!(#maps) - 12 functions
- [🔢 Num]!(#num) - 14 functions
- [⛓️ Slices]!(#slices) - 14 functions
- [🌊 Streams]!(#streams) - 26 functions
- [🔞 Zero]!(#zero) - 2 functions
Package db provides a unified set of abstractions, interfaces, and utilities for database access, transaction management, migrations, and efficient bulk operations across multiple backends.
Features:
- Backend-agnostic interfaces for SQL (Postgres, ClickHouse), MongoDB, and Redis.
- Context and transaction management with hooks for after-commit actions.
- Executor interfaces for read-only, read-write, and transactional operations.
- Bulk DML helpers: efficient bulk insert, update, and upsert with conflict handling.
- Migration helpers for Postgres and ClickHouse using golang-migrate.
- Type utilities for nullable JSON, array types, and custom scanning.
- Common error types and helpers for consistent error handling.
- Query helpers for generic, type-safe data access patterns.
Main Interfaces:
- Handler, Querier, Tx, Result, Rows, Row: Abstract over database drivers.
- Context: Extends context.Context with database query and transaction hooks.
- Executor, ExecutorRO, ExecutorRW: Transactional execution patterns.
- Bulkable, BulkableRanger: Bulk DML abstractions.
Backend Adapters:
- db_pgx.go: Postgres (pgx) support
- db_clickhouse.go: ClickHouse support
- db_mongo.go: MongoDB support
- db_redis.go: Redis support
Utilities:
- utils_bulk_insert.go, utils_bulk_update.go, utils_bulk_upsert.go: Bulk DML
- utils_in_clause.go, utils_order_clause.go, utils_query.go: Query helpers
- types.go: NullJSON, NullJSONArray, and more
- errors.go: Common error values and helpers
- migrate.go, migrations_postgres.go, migrations_clickhouse.go: Migration helpers
Example:
import ( "github.com/sonirico/vago/db" "github.com/sonirico/vago/lol")
Setup a logger and a database handler (e.g., pgx)logger := lol.NewLogger()handler, _ := db.OpenPgxConn(logger, "postgres://user:pass@localhost/db", false)executor := db.NewExecutor(logger, handler)
Run a transactional operation: either all operations succeed, or none are appliederr := executor.DoWithTx(ctx, func(ctx db.Context) error { Multiple DB operations in a transaction if _, err := ctx.Querier().ExecContext(ctx, "INSERT INTO users (name) VALUES ($1)", "alice"); err != nil { return err } if _, err := ctx.Querier().ExecContext(ctx, "INSERT INTO accounts (user) VALUES ($1)", "alice"); err != nil { return err } If any error is returned, all changes are rolled back return nil})Functions
Section titled “Functions”- [BulkInsertSQL]!(#db-bulkinsertsql)
- [BulkUpdateSQL]!(#db-bulkupdatesql)
- [BulkUpsertSQL]!(#db-bulkupsertsql)
- [Executor]!(#db-executor)
- [In]!(#db-in)
- [OrderBy_usage]!(#db-orderby_usage)
db BulkInsertSQL
Section titled “db BulkInsertSQL”ExampleBulkInsertSQL demonstrates how to use BulkInsertSQL to generate an SQL statement for bulk insertion.
Code
func ExampleBulkInsertSQL() { rows := BulkRanger[Bulkable]!([]Bulkable{ &mockBulkable{ ColsVal: []string{"id", "name", "value"}, RowVal: []any{1, "foo", 100}, }, &mockBulkable{ ColsVal: []string{"id", "name", "value"}, RowVal: []any{2, "bar", 200}, }, }) query, args, _ := BulkInsertSQL(rows, "my_table") fmt.Println("SQL:", normalizeSQL(query)) fmt.Println("ARGS:", args) // Output: // SQL: INSERT INTO my_table (id,name,value) VALUES ($1,$2,$3),($4,$5,$6) // ARGS: [1 foo 100 2 bar 200]}[⬆️ Back to Top]!(#table-of-contents)
db BulkUpdateSQL
Section titled “db BulkUpdateSQL”ExampleBulkUpdateSQL demonstrates how to use BulkUpdateSQL to generate an SQL statement for bulk updates.
Code
func ExampleBulkUpdateSQL() { rows := mockBulkUpdate{ &mockBulkUpdatable{ pk: [2]string{"int", "id"}, cols: [][2]string{{"int", "value"}, {"text", "name"}}, vals: []any{1, "foo", 100, "bar"}, }, &mockBulkUpdatable{ pk: [2]string{"int", "id"}, cols: [][2]string{{"int", "value"}, {"text", "name"}}, vals: []any{2, "baz", 200, "qux"}, }, } query, args, _ := BulkUpdateSQL(rows, "my_table") fmt.Println("SQL:", normalizeSQL(query)) fmt.Println("ARGS:", args) // Output: // SQL: UPDATE my_table SET value = bulk_update_tmp.value::int,name = bulk_update_tmp.name::text FROM (VALUES ($1::int, $2::int, $3::text), ($4::int, $5::int, $6::text)) as bulk_update_tmp(id, value, name) WHERE my_table.id::int = bulk_update_tmp.id::int // ARGS: [1 foo 100 bar 2 baz 200 qux]}[⬆️ Back to Top]!(#table-of-contents)
db BulkUpsertSQL
Section titled “db BulkUpsertSQL”Example for BulkUpsertSQL with update on conflict clause
Code
func ExampleBulkUpsertSQL() { rows := BulkRanger[Bulkable]!([]Bulkable{ &mockBulkable{ PKVal: []string{"id"}, UniqueKeysVal: []string{"unique_key"}, IncludePKVal: true, ColsVal: []string{"id", "unique_key", "value"}, RowVal: []any{1, "abc", 100}, }, }) onConflictUpdate := false query, args, _ := BulkUpsertSQL(rows, "my_table", onConflictUpdate) fmt.Println("SQL:", normalizeSQL(query)) fmt.Println("ARGS:", args)
fmt.Println("--")
onConflictUpdate = true query, args, _ = BulkUpsertSQL(rows, "my_table", onConflictUpdate) fmt.Println("SQL:", normalizeSQL(query)) fmt.Println("ARGS:", args)
// Output: // SQL: INSERT INTO my_table (id,unique_key,value) VALUES ($1,$2,$3) ON CONFLICT (unique_key) DO NOTHING RETURNING id,unique_key,value // ARGS: [1 abc 100] // -- // SQL: INSERT INTO my_table (id,unique_key,value) VALUES ($1,$2,$3) ON CONFLICT (unique_key) DO UPDATE SET id = EXCLUDED.id,unique_key = EXCLUDED.unique_key,value = EXCLUDED.value RETURNING id,unique_key,value // ARGS: [1 abc 100]}[⬆️ Back to Top]!(#table-of-contents)
db Executor
Section titled “db Executor”Example for Do and DoWithTx usage with a database service and context.
Code
func ExampleExecutor() { db, mock, _ := sqlmock.New( sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) defer db.Close() log := lol.ZeroTestLogger
// Setup mock expectations mock.ExpectQuery("SELECT 1;"). WillReturnRows(sqlmock.NewRows([]string{"n"}).AddRow(1))
ex := newDatabaseSqlExecutor(log, db)
err := ex.Do(context.Background(), func(ctx Context) error { var n int return ctx.Querier(). QueryRowContext(ctx, "SELECT 1;").Scan(&n) }) fmt.Println("Do error:", err)
mock.ExpectBegin() mock.ExpectQuery("SELECT 2;"). WillReturnRows(sqlmock.NewRows([]string{"n"}).AddRow(2)) mock.ExpectCommit()
err = ex.DoWithTx(context.Background(), func(ctx Context) error { var n int return ctx.Querier().QueryRowContext(ctx, "SELECT 2;").Scan(&n) }) fmt.Println("DoWithTx error:", err)
// Output: // Do error: <nil> // DoWithTx error: <nil>}[⬆️ Back to Top]!(#table-of-contents)
ExampleIn demonstrates how to use the In function to generate an SQL IN clause and its arguments.
Code
func ExampleIn() { args := []any{"foo"} inArgs := []int{1, 2, 3} s, a := In(args, inArgs) fmt.Println(s) fmt.Println(a) // Output: // ($2,$3,$4) // [foo 1 2 3]}[⬆️ Back to Top]!(#table-of-contents)
db OrderBy_usage
Section titled “db OrderBy_usage”ExampleOrderBy_usage demonstrates how to use OrderBy types to generate SQL ORDER BY clauses.
Code
func ExampleOrderBy_usage() { fmt.Println(OrderASC.FullClause("foo")) fmt.Println(OrderDESC.FullClause("foo")) // Output: // ORDER BY foo ASC // ORDER BY foo DESC}[⬆️ Back to Top]!(#table-of-contents)
[⬆️ Back to Top]!(#table-of-contents)
Package ent provides utilities for managing environment variables in a type-safe manner.
Functions
Section titled “Functions”- [Bool]!(#ent-bool)
- [CondStrOrPanic]!(#ent-condstrorpanic)
- [Contains]!(#ent-contains)
- [Duration]!(#ent-duration)
- [Enum]!(#ent-enum)
- [EnumOrPanic]!(#ent-enumorpanic)
- [FixedStrOrPanic]!(#ent-fixedstrorpanic)
- [Float64]!(#ent-float64)
- [Get]!(#ent-get)
- [Int]!(#ent-int)
- [Int64]!(#ent-int64)
- [Int64OrPanic]!(#ent-int64orpanic)
- [IntOrPanic]!(#ent-intorpanic)
- [JSON]!(#ent-json)
- [SliceInt]!(#ent-sliceint)
- [SliceStr]!(#ent-slicestr)
- [Str]!(#ent-str)
- [StrOrPanic]!(#ent-strorpanic)
ent Bool
Section titled “ent Bool”ExampleBool demonstrates how to retrieve boolean environment variables with various true/false representations.
Code
func ExampleBool() { // Set environment variable os.Setenv("DEBUG", "true") defer os.Unsetenv("DEBUG")
debug := Bool("DEBUG", false) fmt.Println(debug) // Output: // // true}[⬆️ Back to Top]!(#table-of-contents)
ent CondStrOrPanic
Section titled “ent CondStrOrPanic”ExampleCondStrOrPanic demonstrates how to conditionally retrieve environment variables with panic on missing values.
Code
func ExampleCondStrOrPanic() { // Set environment variable os.Setenv("DEBUG_MODE", "true") defer os.Unsetenv("DEBUG_MODE")
// Get value only if condition is true debugMode := CondStrOrPanic(true, "DEBUG_MODE") fmt.Println(debugMode)
// Returns empty string if condition is false emptyValue := CondStrOrPanic(false, "DEBUG_MODE") fmt.Println(emptyValue) // Output: // // true //}[⬆️ Back to Top]!(#table-of-contents)
ent Contains
Section titled “ent Contains”ExampleContains demonstrates how to check if a value exists in a slice of strings.
Code
func ExampleContains() { fruits := []string{"apple", "banana", "cherry"}
hasBanana := contains(fruits, "banana") fmt.Println(hasBanana)
hasOrange := contains(fruits, "orange") fmt.Println(hasOrange) // Output: // // true // false}[⬆️ Back to Top]!(#table-of-contents)
ent Duration
Section titled “ent Duration”ExampleDuration demonstrates how to retrieve time.Duration environment variables with fallback values.
Code
func ExampleDuration() { // Set environment variable os.Setenv("REQUEST_TIMEOUT", "30s") defer os.Unsetenv("REQUEST_TIMEOUT")
timeout := Duration("REQUEST_TIMEOUT", 10*time.Second) fmt.Println(timeout) // Output: // // 30s}[⬆️ Back to Top]!(#table-of-contents)
ent Enum
Section titled “ent Enum”ExampleEnum demonstrates how to retrieve environment variables with validation against allowed values.
Code
func ExampleEnum() { // Set environment variable os.Setenv("ENV", "staging") defer os.Unsetenv("ENV")
env := Enum("ENV", "dev", "dev", "staging", "prod") fmt.Println(env) // Output: // // staging}[⬆️ Back to Top]!(#table-of-contents)
ent EnumOrPanic
Section titled “ent EnumOrPanic”ExampleEnumOrPanic demonstrates how to retrieve required environment variables with validation against allowed values, panicking if invalid.
Code
func ExampleEnumOrPanic() { // Set environment variable os.Setenv("LOG_LEVEL", "info") defer os.Unsetenv("LOG_LEVEL")
logLevel := EnumOrPanic("LOG_LEVEL", "debug", "info", "warn", "error") fmt.Println(logLevel) // Output: // // info}[⬆️ Back to Top]!(#table-of-contents)
ent FixedStrOrPanic
Section titled “ent FixedStrOrPanic”ExampleFixedStrOrPanic demonstrates how to retrieve environment variables with length validation.
Code
func ExampleFixedStrOrPanic() { // Set environment variable with exact length os.Setenv("API_KEY", "abc123") defer os.Unsetenv("API_KEY")
// Get value with length validation apiKey := FixedStrOrPanic("API_KEY", 6) fmt.Println(apiKey) // Output: // // abc123}[⬆️ Back to Top]!(#table-of-contents)
ent Float64
Section titled “ent Float64”ExampleFloat64 demonstrates how to retrieve float64 environment variables with fallback values.
Code
func ExampleFloat64() { // Set environment variable os.Setenv("PRICE", "19.99") defer os.Unsetenv("PRICE")
price := Float64("PRICE", 0.0) fmt.Println(price) // Output: // // 19.99}[⬆️ Back to Top]!(#table-of-contents)
ent Get
Section titled “ent Get”ExampleGet demonstrates how to retrieve environment variables with fallback values.
Code
func ExampleGet() { // Set an environment variable os.Setenv("APP_NAME", "MyApplication") defer os.Unsetenv("APP_NAME")
// Get existing env var appName := Get("APP_NAME", "DefaultApp") fmt.Println(appName)
// Get non-existing env var with fallback dbHost := Get("DB_HOST", "localhost") fmt.Println(dbHost) // Output: // // MyApplication // localhost}[⬆️ Back to Top]!(#table-of-contents)
ent Int
Section titled “ent Int”ExampleInt demonstrates how to retrieve integer environment variables with fallback values.
Code
func ExampleInt() { // Set environment variable os.Setenv("WORKER_COUNT", "4") defer os.Unsetenv("WORKER_COUNT")
workers := Int("WORKER_COUNT", 1) fmt.Println(workers) // Output: // // 4}[⬆️ Back to Top]!(#table-of-contents)
ent Int64
Section titled “ent Int64”ExampleInt64 demonstrates how to retrieve int64 environment variables with fallback values.
Code
func ExampleInt64() { // Set environment variable os.Setenv("MAX_CONNECTIONS", "100") defer os.Unsetenv("MAX_CONNECTIONS")
maxConn := Int64("MAX_CONNECTIONS", 50) fmt.Println(maxConn) // Output: // // 100}[⬆️ Back to Top]!(#table-of-contents)
ent Int64OrPanic
Section titled “ent Int64OrPanic”ExampleInt64OrPanic demonstrates how to retrieve required int64 environment variables that panic if missing or invalid.
Code
func ExampleInt64OrPanic() { // Set required environment variable os.Setenv("PORT", "8080") defer os.Unsetenv("PORT")
port := Int64OrPanic("PORT") fmt.Println(port) // Output: // // 8080}[⬆️ Back to Top]!(#table-of-contents)
ent IntOrPanic
Section titled “ent IntOrPanic”ExampleIntOrPanic demonstrates how to retrieve required integer environment variables that panic if missing or invalid.
Code
func ExampleIntOrPanic() { // Set required environment variable os.Setenv("TIMEOUT", "30") defer os.Unsetenv("TIMEOUT")
timeout := IntOrPanic("TIMEOUT") fmt.Println(timeout) // Output: // // 30}[⬆️ Back to Top]!(#table-of-contents)
ent JSON
Section titled “ent JSON”ExampleJSON demonstrates how to parse JSON environment variables into Go structs with type safety.
Code
func ExampleJSON() { type Config struct { Host string `json:"host"` Port int `json:"port"` }
// Set environment variable os.Setenv("DB_CONFIG", `{"host":"localhost","port":5432}`) defer os.Unsetenv("DB_CONFIG")
config, err := JSON[Config]!("DB_CONFIG", `{"host":"127.0.0.1","port":3306}`) if err != nil { panic(err) } fmt.Println(config.Host) // Output: // // localhost}[⬆️ Back to Top]!(#table-of-contents)
ent SliceInt
Section titled “ent SliceInt”ExampleSliceInt demonstrates how to retrieve integer slice environment variables from comma-separated values.
Code
func ExampleSliceInt() { // Set environment variable os.Setenv("PORTS", "8080,8081,8082") defer os.Unsetenv("PORTS")
ports := SliceInt("PORTS", []int{3000}) fmt.Println(len(ports)) // Output: // // 3}[⬆️ Back to Top]!(#table-of-contents)
ent SliceStr
Section titled “ent SliceStr”ExampleSliceStr demonstrates how to retrieve string slice environment variables from comma-separated values.
Code
func ExampleSliceStr() { // Set environment variable os.Setenv("ALLOWED_HOSTS", "localhost,127.0.0.1,example.com") defer os.Unsetenv("ALLOWED_HOSTS")
hosts := SliceStr("ALLOWED_HOSTS", []string{"localhost"}) fmt.Println(len(hosts)) // Output: // // 3}[⬆️ Back to Top]!(#table-of-contents)
ent Str
Section titled “ent Str”ExampleStr demonstrates how to retrieve string environment variables with fallback values.
Code
func ExampleStr() { // Set environment variable os.Setenv("USER_NAME", "john_doe") defer os.Unsetenv("USER_NAME")
username := Str("USER_NAME", "anonymous") fmt.Println(username) // Output: // // john_doe}[⬆️ Back to Top]!(#table-of-contents)
ent StrOrPanic
Section titled “ent StrOrPanic”ExampleStrOrPanic demonstrates how to retrieve required environment variables that panic if missing.
Code
func ExampleStrOrPanic() { // Set required environment variable os.Setenv("REQUIRED_CONFIG", "important_value") defer os.Unsetenv("REQUIRED_CONFIG")
// Get required value (panics if missing) config := StrOrPanic("REQUIRED_CONFIG") fmt.Println(config) // Output: // // important_value}[⬆️ Back to Top]!(#table-of-contents)
[⬆️ Back to Top]!(#table-of-contents)
Functional programming utilities including Option and Result types.
Functions
Section titled “Functions”- [Err]!(#fp-err)
- [None]!(#fp-none)
- [Ok]!(#fp-ok)
- [OkZero]!(#fp-okzero)
- [Option]!(#fp-option)
- [OptionFromPtr]!(#fp-optionfromptr)
- [OptionFromTuple]!(#fp-optionfromtuple)
- [Option_Map]!(#fp-option_map)
- [Option_Match]!(#fp-option_match)
- [Option_Or]!(#fp-option_or)
- [Result]!(#fp-result)
- [Result_Map]!(#fp-result_map)
- [Result_Match]!(#fp-result_match)
- [Result_Or]!(#fp-result_or)
- [Some]!(#fp-some)
fp Err
Section titled “fp Err”ExampleErr demonstrates creating an error Result.
Code
func ExampleErr() { // Create an error result result := Err[string]!(errors.New("something failed"))
fmt.Printf("Is error: %t\n", result.IsErr()) fmt.Printf("Value: %s\n", result.UnwrapOr("default"))
// Output: // Is error: true // Value: default}[⬆️ Back to Top]!(#table-of-contents)
fp None
Section titled “fp None”ExampleNone demonstrates creating an empty Option.
Code
func ExampleNone() { // Create an empty Option empty := None[string]!()
fmt.Printf("Has value: %t\n", empty.IsSome()) fmt.Printf("Value: %s\n", empty.UnwrapOr("default"))
// Output: // Has value: false // Value: default}[⬆️ Back to Top]!(#table-of-contents)
ExampleOk demonstrates creating a successful Result.
Code
func ExampleOk() { // Create a successful result result := Ok("Success!")
fmt.Printf("Is ok: %t\n", result.IsOk()) fmt.Printf("Value: %s\n", result.UnwrapOr("default"))
// Output: // Is ok: true // Value: Success!}[⬆️ Back to Top]!(#table-of-contents)
fp OkZero
Section titled “fp OkZero”ExampleOkZero demonstrates creating a Result with zero value.
Code
func ExampleOkZero() { // Create a successful result with zero value result := OkZero[int]!()
fmt.Printf("Is ok: %t\n", result.IsOk()) fmt.Printf("Value: %d\n", result.UnwrapOr(-1))
// Output: // Is ok: true // Value: 0}[⬆️ Back to Top]!(#table-of-contents)
fp Option
Section titled “fp Option”ExampleOption demonstrates basic usage of the Option type.
Code
func ExampleOption() { // Create Some and None options someValue := Some(42) noneValue := None[int]!()
// Check if options have values fmt.Printf("Some has value: %v\n", someValue.IsSome()) fmt.Printf("None has value: %v\n", noneValue.IsSome())
// Extract values safely if value, ok := someValue.Unwrap(); ok { fmt.Printf("Value: %d\n", value) }
// Output: // Some has value: true // None has value: false // Value: 42}[⬆️ Back to Top]!(#table-of-contents)
fp OptionFromPtr
Section titled “fp OptionFromPtr”ExampleOptionFromPtr demonstrates creating Option from a pointer.
Code
func ExampleOptionFromPtr() { // From valid pointer value := "hello" opt1 := OptionFromPtr(&value)
// From nil pointer var nilPtr *string opt2 := OptionFromPtr(nilPtr)
fmt.Printf("From pointer: %s\n", opt1.UnwrapOr("empty")) fmt.Printf("From nil: %s\n", opt2.UnwrapOr("empty"))
// Output: // From pointer: hello // From nil: empty}[⬆️ Back to Top]!(#table-of-contents)
fp OptionFromTuple
Section titled “fp OptionFromTuple”ExampleOptionFromTuple demonstrates creating Option from a tuple pattern.
Code
func ExampleOptionFromTuple() { // Common Go pattern: value, ok getValue := func(key string) (string, bool) { data := map[string]string{"name": "Alice", "age": "25"} value, ok := data[key] return value, ok }
// Convert to Option nameOpt := OptionFromTuple(getValue("name")) missingOpt := OptionFromTuple(getValue("missing"))
fmt.Printf("Name: %s\n", nameOpt.UnwrapOr("unknown")) fmt.Printf("Missing: %s\n", missingOpt.UnwrapOr("unknown"))
// Output: // Name: Alice // Missing: unknown}[⬆️ Back to Top]!(#table-of-contents)
fp Option_Map
Section titled “fp Option_Map”ExampleOption_Map demonstrates transforming values inside Option.
Code
func ExampleOption_Map() { // Start with an optional number maybeNumber := Some(5)
// Transform it to its square maybeSquare := maybeNumber.Map(func(x int) int { return x * x })
// Transform None value noneNumber := None[int]!() noneSquare := noneNumber.Map(func(x int) int { return x * x })
fmt.Printf("Square of 5: %v\n", maybeSquare.UnwrapOr(0)) fmt.Printf("Square of None: %v\n", noneSquare.UnwrapOr(-1))
// Output: // Square of 5: 25 // Square of None: -1}[⬆️ Back to Top]!(#table-of-contents)
fp Option_Match
Section titled “fp Option_Match”ExampleOption_Match demonstrates pattern matching with Option.
Code
func ExampleOption_Match() { // Helper function that may return a value getValue := func(id int) Option[string] { if id > 0 { return Some(fmt.Sprintf("User_%d", id)) } return None[string]!() }
// Pattern match on the result validUser := getValue(42) invalidUser := getValue(-1)
result1 := validUser.Match( func(user string) Option[string] { return Some("Found: " + user) }, func() Option[string] { return Some("No user found") }, )
result2 := invalidUser.Match( func(user string) Option[string] { return Some("Found: " + user) }, func() Option[string] { return Some("No user found") }, )
fmt.Printf("Valid user: %s\n", result1.UnwrapOr("")) fmt.Printf("Invalid user: %s\n", result2.UnwrapOr(""))
// Output: // Valid user: Found: User_42 // Invalid user: No user found}[⬆️ Back to Top]!(#table-of-contents)
fp Option_Or
Section titled “fp Option_Or”ExampleOption_Or demonstrates providing fallback values.
Code
func ExampleOption_Or() { // Create some options primary := None[string]!() secondary := Some("backup") tertiary := Some("fallback")
// Chain fallbacks result := primary.Or(secondary).Or(tertiary)
fmt.Printf("Result: %s\n", result.UnwrapOr("default"))
// Output: // Result: backup}[⬆️ Back to Top]!(#table-of-contents)
fp Result
Section titled “fp Result”ExampleResult demonstrates basic usage of the Result type.
Code
func ExampleResult() { // Create successful and error results success := Ok("Hello, World!") failure := Err[string]!(errors.New("something went wrong"))
// Check if results are ok fmt.Printf("Success is ok: %v\n", success.IsOk()) fmt.Printf("Failure is ok: %v\n", failure.IsOk())
// Extract values safely if value, err := success.Unwrap(); err == nil { fmt.Printf("Success value: %s\n", value) }
if _, err := failure.Unwrap(); err != nil { fmt.Printf("Failure error: %v\n", err) }
// Output: // Success is ok: true // Failure is ok: false // Success value: Hello, World! // Failure error: something went wrong}[⬆️ Back to Top]!(#table-of-contents)
fp Result_Map
Section titled “fp Result_Map”ExampleResult_Map demonstrates transforming values inside Result.
Code
func ExampleResult_Map() { // Start with a result containing a number result := Ok(5)
// Transform to its square squared := result.Map(func(x int) int { return x * x })
// Transform an error result errorResult := Err[int]!(errors.New("invalid input")) errorSquared := errorResult.Map(func(x int) int { return x * x })
fmt.Printf("Square of 5: %v\n", squared.UnwrapOr(0)) fmt.Printf("Square of error: %v\n", errorSquared.UnwrapOr(-1))
// Output: // Square of 5: 25 // Square of error: -1}[⬆️ Back to Top]!(#table-of-contents)
fp Result_Match
Section titled “fp Result_Match”ExampleResult_Match demonstrates pattern matching with Result.
Code
func ExampleResult_Match() { // Helper function that may fail divide := func(x, y int) Result[int] { if y == 0 { return Err[int]!(errors.New("division by zero")) } return Ok(x / y) }
// Pattern match on results success := divide(10, 2) failure := divide(10, 0)
result1 := success.Match( func(value int) Result[int] { return Ok(value * 2) }, func(err error) Result[int] { return Err[int]!(fmt.Errorf("handled: %w", err)) }, )
result2 := failure.Match( func(value int) Result[int] { return Ok(value * 2) }, func(err error) Result[int] { return Err[int]!(fmt.Errorf("handled: %w", err)) }, )
fmt.Printf("Success result: %v\n", result1.UnwrapOr(-1)) fmt.Printf("Failure handled: %v\n", result2.IsErr())
// Output: // Success result: 10 // Failure handled: true}[⬆️ Back to Top]!(#table-of-contents)
fp Result_Or
Section titled “fp Result_Or”ExampleResult_Or demonstrates providing fallback results.
Code
func ExampleResult_Or() { // Create primary and fallback results primary := Err[string]!(errors.New("primary failed")) fallback := Ok("fallback value")
// Use fallback when primary fails result := primary.Or(fallback)
fmt.Printf("Result: %s\n", result.UnwrapOr("default"))
// Output: // Result: fallback value}[⬆️ Back to Top]!(#table-of-contents)
fp Some
Section titled “fp Some”ExampleSome demonstrates creating an Option with a value.
Code
func ExampleSome() { // Create an Option containing a string message := Some("Hello, World!")
fmt.Printf("Has value: %t\n", message.IsSome()) fmt.Printf("Value: %s\n", message.UnwrapOr("default"))
// Output: // Has value: true // Value: Hello, World!}[⬆️ Back to Top]!(#table-of-contents)
[⬆️ Back to Top]!(#table-of-contents)
Package lol (lots of logs) provides a unified logging interface with multiple backends.
This package offers a simple, structured logging interface that can be backed by different logging implementations. Currently it supports zerolog as the primary backend.
Key features:
- Structured logging with fields
- Multiple log levels (trace, debug, info, warn, error, fatal, panic)
- APM trace context integration
- Environment-aware configuration
- Testing utilities
Basic usage:
logger := lol.NewZerolog( lol.WithFields(lol.Fields{"service": "myapp"}), lol.WithEnv("production"), lol.WithLevel("info"), lol.WithWriter(os.Stdout), lol.WithAPM(lol.APMConfig{Enabled: true}),)
logger.Info("Application started")logger.WithField("user_id", 123).Warn("User action")For testing:
testLogger := lol.NewTest()testLogger.Error("This won't be printed")Functions
Section titled “Functions”- [Logger_Trace]!(#lol-logger_trace)
- [Logger_WithField]!(#lol-logger_withfield)
- [Logger_WithTrace]!(#lol-logger_withtrace)
- [NewZerolog]!(#lol-newzerolog)
lol Logger_Trace
Section titled “lol Logger_Trace”ExampleLogger_Trace demonstrates different log levels
Code
func ExampleLogger_Trace() { var buf bytes.Buffer
logger := NewZerolog( WithFields(Fields{"component": "auth"}), WithEnv(EnvDev), WithLevel(LevelTrace), // Set to trace level to see all messages WithWriter(&buf), )
// Log at different levels logger.Trace("Entering authentication function") logger.Debug("Validating user credentials") logger.Info("User authentication successful") logger.Warn("Rate limit approaching") logger.Error("Authentication failed")
output := buf.String() fmt.Printf( "Contains trace message: %t\n", bytes.Contains([]byte(output), []byte("Entering authentication")), ) fmt.Printf( "Contains debug message: %t\n", bytes.Contains([]byte(output), []byte("Validating user")), ) fmt.Printf( "Contains info message: %t\n", bytes.Contains([]byte(output), []byte("authentication successful")), ) fmt.Printf("Contains warn message: %t\n", bytes.Contains([]byte(output), []byte("Rate limit"))) fmt.Printf( "Contains error message: %t\n", bytes.Contains([]byte(output), []byte("Authentication failed")), )
// Output: // Contains trace message: true // Contains debug message: true // Contains info message: true // Contains warn message: true // Contains error message: true}[⬆️ Back to Top]!(#table-of-contents)
lol Logger_WithField
Section titled “lol Logger_WithField”ExampleLogger_WithField demonstrates adding contextual fields to log messages
Code
func ExampleLogger_WithField() { var buf bytes.Buffer
logger := NewZerolog( WithFields(Fields{"app": "demo"}), WithEnv(EnvDev), WithLevel(LevelDebug), WithWriter(&buf), )
// Chain multiple fields enrichedLogger := logger.WithField("request_id", "req-123"). WithField("user_agent", "test-client") enrichedLogger.Info("Processing request")
// Add more context enrichedLogger.WithField("duration_ms", 45).Info("Request completed")
output := buf.String() fmt.Printf( "Output contains 'request_id': %t\n", bytes.Contains([]byte(output), []byte("request_id")), ) fmt.Printf( "Output contains 'user_agent': %t\n", bytes.Contains([]byte(output), []byte("user_agent")), ) fmt.Printf( "Output contains 'duration_ms': %t\n", bytes.Contains([]byte(output), []byte("duration_ms")), )
// Output: // Output contains 'request_id': true // Output contains 'user_agent': true // Output contains 'duration_ms': true}[⬆️ Back to Top]!(#table-of-contents)
lol Logger_WithTrace
Section titled “lol Logger_WithTrace”ExampleLogger_WithTrace demonstrates APM trace context integration
Code
func ExampleLogger_WithTrace() { var buf bytes.Buffer
logger := NewZerolog( WithFields(Fields{"service": "payment-service"}), WithEnv(EnvDev), WithLevel(LevelInfo), WithWriter(&buf), WithApm(), // Enable APM tracing )
// Create an APM transaction (simulating real APM integration) tracer := apm.DefaultTracer() tx := tracer.StartTransaction("payment-processing", "request") defer tx.End()
// Create context with the transaction ctx := apm.ContextWithTransaction(context.Background(), tx)
// Start a span for more detailed tracing span, ctx := apm.StartSpan(ctx, "payment-validation", "internal") defer span.End()
// Create a logger with trace context tracedLogger := logger.WithTrace(ctx)
// Log with trace context - these should include APM trace fields tracedLogger.Info("Processing payment request") tracedLogger.WithField("payment_id", "pay_123"). WithField("amount", 99.99). Info("Payment validation started")
// Log without trace context for comparison logger.Info("Regular log message without trace context")
output := buf.String() fmt.Printf( "Output contains 'Processing payment': %t\n", bytes.Contains([]byte(output), []byte("Processing payment")), ) fmt.Printf( "Output contains 'payment_id': %t\n", bytes.Contains([]byte(output), []byte("payment_id")), ) fmt.Printf( "Output contains 'service': %t\n", bytes.Contains([]byte(output), []byte("service")), )
// Check for APM trace fields in the output // The apmzerolog hook should add these fields when WithTrace is used fmt.Printf( "Output contains trace information: %t\n", bytes.Contains([]byte(output), []byte("trace")) || bytes.Contains([]byte(output), []byte("transaction")) || bytes.Contains([]byte(output), []byte("span")), )
// Output: // Output contains 'Processing payment': true // Output contains 'payment_id': true // Output contains 'service': true // Output contains trace information: true}[⬆️ Back to Top]!(#table-of-contents)
lol NewZerolog
Section titled “lol NewZerolog”ExampleNewZerolog demonstrates creating a structured logger with zerolog backend
Code
func ExampleNewZerolog() { // Create a logger with custom fields and configuration var buf bytes.Buffer
logger := NewZerolog( WithFields(Fields{"service": "example-app", "version": "1.0.0"}), WithEnv(EnvProd), WithLevel(LevelInfo), WithWriter(&buf), )
// Log some messages logger.Info("Application started successfully") logger.WithField("user_id", 123).WithField("action", "login").Info("User logged in") logger.Warn("This is a warning message")
fmt.Printf( "Logged output contains 'Application started': %t\n", bytes.Contains(buf.Bytes(), []byte("Application started")), ) fmt.Printf( "Logged output contains 'user_id': %t\n", bytes.Contains(buf.Bytes(), []byte("user_id")), ) fmt.Printf( "Logged output contains 'service': %t\n", bytes.Contains(buf.Bytes(), []byte("service")), )
fmt.Printf( "Logged output contains 'version': %t\n", bytes.Contains(buf.Bytes(), []byte("version")), )
// Output: // Logged output contains 'Application started': true // Logged output contains 'user_id': true // Logged output contains 'service': true // Logged output contains 'version': true}[⬆️ Back to Top]!(#table-of-contents)
[⬆️ Back to Top]!(#table-of-contents)
🗝️ Maps
Section titled “🗝️ Maps”Package maps provides generic utility functions to work with Go maps. It offers a functional approach to common map operations like filtering, mapping, reducing, and comparing maps.
Functions
Section titled “Functions”- [Equals]!(#maps-equals)
- [Filter]!(#maps-filter)
- [FilterMap]!(#maps-filtermap)
- [FilterMapTuple]!(#maps-filtermaptuple)
- [Fold]!(#maps-fold)
- [Keys]!(#maps-keys)
- [Map]!(#maps-map)
- [Reduce]!(#maps-reduce)
- [SeqKeys]!(#maps-seqkeys)
- [SeqValues]!(#maps-seqvalues)
- [Slice]!(#maps-slice)
- [Values]!(#maps-values)
maps Equals
Section titled “maps Equals”ExampleEquals demonstrates comparing two maps for equality.
Code
func ExampleEquals() { // Create two maps map1 := map[string]int{"a": 1, "b": 2, "c": 3} map2 := map[string]int{"a": 1, "b": 2, "c": 3} map3 := map[string]int{"a": 1, "b": 2, "c": 4}
// Compare using equality function equal1 := Equals(map1, map2, func(x, y int) bool { return x == y }) equal2 := Equals(map1, map3, func(x, y int) bool { return x == y })
fmt.Printf("map1 == map2: %t\n", equal1) fmt.Printf("map1 == map3: %t\n", equal2) // Output: // map1 == map2: true // map1 == map3: false}[⬆️ Back to Top]!(#table-of-contents)
maps Filter
Section titled “maps Filter”ExampleFilter demonstrates filtering a map by key-value pairs.
Code
func ExampleFilter() { // Create a map of products to prices prices := map[string]int{ "apple": 100, "banana": 50, "cherry": 200, "date": 75, }
// Keep only items that cost more than 75 expensive := Filter(prices, func(product string, price int) bool { return price > 75 })
fmt.Printf("Expensive items count: %d\n", len(expensive)) // Output: Expensive items count: 2}[⬆️ Back to Top]!(#table-of-contents)
maps FilterMap
Section titled “maps FilterMap”ExampleFilterMap demonstrates filtering and transforming in a single operation.
Code
func ExampleFilterMap() { // Create a map of names to ages ages := map[string]int{ "Alice": 25, "Bob": 17, "Carol": 30, "Dave": 16, }
// Keep only adults and transform to ID format adults := FilterMap(ages, func(name string, age int) fp.Option[tuples.Tuple2[string, string]] { if age >= 18 { id := fmt.Sprintf("ID_%s_%d", name, age) return fp.Some(tuples.Tuple2[string, string]{V1: name, V2: id}) } return fp.None[tuples.Tuple2[string, string]]!() })
fmt.Printf("Adult count: %d\n", len(adults)) // Output: Adult count: 2}[⬆️ Back to Top]!(#table-of-contents)
maps FilterMapTuple
Section titled “maps FilterMapTuple”ExampleFilterMapTuple demonstrates filtering and transforming using tuple returns.
Code
func ExampleFilterMapTuple() { // Create a map of scores scores := map[string]int{ "Alice": 85, "Bob": 70, "Carol": 95, "Dave": 60, }
// Keep high scores and convert to grade format grades := FilterMapTuple(scores, func(name string, score int) (string, string, bool) { if score >= 80 { var grade string if score >= 90 { grade = "A" } else { grade = "B" } return name, grade, true } return "", "", false })
fmt.Printf("High performers: %d\n", len(grades)) fmt.Printf("Alice's grade: %s\n", grades["Alice"]) // Output: // High performers: 2 // Alice's grade: B}[⬆️ Back to Top]!(#table-of-contents)
maps Fold
Section titled “maps Fold”ExampleFold demonstrates folding a map with an initial value.
Code
func ExampleFold() { // Create a map of item prices prices := map[string]float64{ "apple": 1.20, "banana": 0.80, "cherry": 2.50, }
// Calculate total with initial tax totalWithTax := Fold(prices, func(acc float64, item string, price float64) float64 { return acc + price*1.1 // Add 10% tax }, 5.0) // Start with 5.0 base fee
fmt.Printf("Total with tax: %.2f\n", totalWithTax) // Output: // Total with tax: 9.95}[⬆️ Back to Top]!(#table-of-contents)
maps Keys
Section titled “maps Keys”ExampleKeys demonstrates extracting all keys from a map.
Code
func ExampleKeys() { // Create a map of products to prices prices := map[string]int{ "apple": 100, "banana": 50, "cherry": 200, }
// Extract all product names products := Keys(prices)
fmt.Printf("Product count: %d\n", len(products)) // Note: map iteration order is not guaranteed // Output: // Product count: 3}[⬆️ Back to Top]!(#table-of-contents)
maps Map
Section titled “maps Map”ExampleMap demonstrates transforming keys and values in a map.
Code
func ExampleMap() { // Create a map of numbers to their names numbers := map[int]string{ 1: "one", 2: "two", 3: "three", }
// Transform to string keys and uppercase values transformed := Map(numbers, func(key int, value string) (string, string) { return fmt.Sprintf("num_%d", key), strings.ToUpper(value) })
fmt.Println(transformed["num_1"]) // Output: ONE}[⬆️ Back to Top]!(#table-of-contents)
maps Reduce
Section titled “maps Reduce”ExampleReduce demonstrates reducing a map to a single value.
Code
func ExampleReduce() { // Create a map of item quantities inventory := map[string]int{ "apples": 10, "bananas": 5, "oranges": 8, }
// Calculate total items (Reduce starts with zero value) total := Reduce(inventory, func(acc int, key string, value int) int { return acc + value })
fmt.Printf("Total items: %d\n", total) // Output: Total items: 23}[⬆️ Back to Top]!(#table-of-contents)
maps SeqKeys
Section titled “maps SeqKeys”ExampleSeqKeys demonstrates iterating over map keys using iterator pattern.
Code
func ExampleSeqKeys() { // Create a map of products to prices prices := map[string]int{ "apple": 100, "banana": 50, "cherry": 200, }
// Iterate over keys lazily keyCount := 0 for range SeqKeys(prices) { keyCount++ }
fmt.Printf("Key count: %d\n", keyCount) // Output: // Key count: 3}[⬆️ Back to Top]!(#table-of-contents)
maps SeqValues
Section titled “maps SeqValues”ExampleSeqValues demonstrates iterating over map values using iterator pattern.
Code
func ExampleSeqValues() { // Create a map of products to prices prices := map[string]int{ "apple": 100, "banana": 50, "cherry": 200, }
// Calculate total using iterator total := 0 for price := range SeqValues(prices) { total += price }
fmt.Printf("Total price: %d\n", total) // Output: // Total price: 350}[⬆️ Back to Top]!(#table-of-contents)
maps Slice
Section titled “maps Slice”ExampleSlice demonstrates converting a map to a slice.
Code
func ExampleSlice() { // Create a map of user data users := map[int]string{ 1: "Alice", 2: "Bob", 3: "Carol", }
// Convert to slice of formatted strings userList := Slice(users, func(id int, name string) string { return fmt.Sprintf("ID:%d Name:%s", id, name) })
fmt.Printf("Users count: %d\n", len(userList)) // Note: map iteration order is not guaranteed // Output: // Users count: 3}[⬆️ Back to Top]!(#table-of-contents)
maps Values
Section titled “maps Values”ExampleValues demonstrates extracting all values from a map.
Code
func ExampleValues() { // Create a map of products to prices prices := map[string]int{ "apple": 100, "banana": 50, "cherry": 200, }
// Extract all prices allPrices := Values(prices)
fmt.Printf("Price count: %d\n", len(allPrices)) // Note: map iteration order is not guaranteed // Output: // Price count: 3}[⬆️ Back to Top]!(#table-of-contents)
[⬆️ Back to Top]!(#table-of-contents)
Numeric utilities including high-precision decimal operations.
Functions
Section titled “Functions”- [Abs]!(#num-abs)
- [Dec_Add]!(#num-dec_add)
- [Dec_Div]!(#num-dec_div)
- [Dec_IsZero]!(#num-dec_iszero)
- [Dec_LessThan]!(#num-dec_lessthan)
- [Dec_Mul]!(#num-dec_mul)
- [Dec_Percent]!(#num-dec_percent)
- [Dec_Round]!(#num-dec_round)
- [Dec_Sub]!(#num-dec_sub)
- [MustDecFromAny]!(#num-mustdecfromany)
- [MustDecFromString]!(#num-mustdecfromstring)
- [NewDecFromFloat]!(#num-newdecfromfloat)
- [NewDecFromInt]!(#num-newdecfromint)
- [NewDecFromString]!(#num-newdecfromstring)
num Abs
Section titled “num Abs”ExampleAbs demonstrates absolute value calculation
Code
func ExampleAbs() { // Calculate absolute values for different types intVal := -42 floatVal := -3.14
absInt := Abs(intVal) absFloat := Abs(floatVal)
fmt.Printf("Original int: %d, Absolute: %d\n", intVal, absInt) fmt.Printf("Original float: %.2f, Absolute: %.2f\n", floatVal, absFloat)
// Output: // Original int: -42, Absolute: 42 // Original float: -3.14, Absolute: 3.14}[⬆️ Back to Top]!(#table-of-contents)
num Dec_Add
Section titled “num Dec_Add”ExampleDec_Add demonstrates decimal addition
Code
func ExampleDec_Add() { // Perform decimal addition price1 := MustDecFromString("123.45") price2 := MustDecFromString("67.89")
total := price1.Add(price2)
fmt.Printf("Price 1: %s\n", price1.String()) fmt.Printf("Price 2: %s\n", price2.String()) fmt.Printf("Total: %s\n", total.String())
// Output: // Price 1: 123.45 // Price 2: 67.89 // Total: 191.34}[⬆️ Back to Top]!(#table-of-contents)
num Dec_Div
Section titled “num Dec_Div”ExampleDec_Div demonstrates decimal division
Code
func ExampleDec_Div() { // Calculate unit price totalCost := MustDecFromString("127.50") quantity := MustDecFromString("25")
unitPrice := totalCost.Div(quantity)
fmt.Printf("Total cost: %s\n", totalCost.String()) fmt.Printf("Quantity: %s\n", quantity.String()) fmt.Printf("Unit price: %s\n", unitPrice.String())
// Output: // Total cost: 127.5 // Quantity: 25 // Unit price: 5.1}[⬆️ Back to Top]!(#table-of-contents)
num Dec_IsZero
Section titled “num Dec_IsZero”ExampleDec_IsZero demonstrates zero checking
Code
func ExampleDec_IsZero() { // Check if decimal is zero zero := Zero nonZero := MustDecFromString("0.01") alsoZero := MustDecFromString("0.00")
fmt.Printf("Zero value: %s, IsZero: %t\n", zero.String(), zero.IsZero()) fmt.Printf("Non-zero value: %s, IsZero: %t\n", nonZero.String(), nonZero.IsZero()) fmt.Printf("Also zero: %s, IsZero: %t\n", alsoZero.String(), alsoZero.IsZero())
// Output: // Zero value: 0, IsZero: true // Non-zero value: 0.01, IsZero: false // Also zero: 0, IsZero: true}[⬆️ Back to Top]!(#table-of-contents)
num Dec_LessThan
Section titled “num Dec_LessThan”ExampleDec_LessThan demonstrates decimal comparison
Code
func ExampleDec_LessThan() { // Compare decimal values price1 := MustDecFromString("99.99") price2 := MustDecFromString("100.00") price3 := MustDecFromString("99.99")
fmt.Printf("Price 1: %s\n", price1.String()) fmt.Printf("Price 2: %s\n", price2.String()) fmt.Printf("Price 3: %s\n", price3.String())
fmt.Printf("Price 1 < Price 2: %t\n", price1.LessThan(price2)) fmt.Printf("Price 1 > Price 2: %t\n", price1.GreaterThan(price2)) fmt.Printf("Price 1 == Price 3: %t\n", price1.Equal(price3)) fmt.Printf("Price 1 <= Price 2: %t\n", price1.LessThanOrEqual(price2))
// Output: // Price 1: 99.99 // Price 2: 100 // Price 3: 99.99 // Price 1 < Price 2: true // Price 1 > Price 2: false // Price 1 == Price 3: true // Price 1 <= Price 2: true}[⬆️ Back to Top]!(#table-of-contents)
num Dec_Mul
Section titled “num Dec_Mul”ExampleDec_Mul demonstrates decimal multiplication
Code
func ExampleDec_Mul() { // Calculate area length := MustDecFromString("12.5") width := MustDecFromString("8.4")
area := length.Mul(width)
fmt.Printf("Length: %s\n", length.String()) fmt.Printf("Width: %s\n", width.String()) fmt.Printf("Area: %s\n", area.String())
// Output: // Length: 12.5 // Width: 8.4 // Area: 105}[⬆️ Back to Top]!(#table-of-contents)
num Dec_Percent
Section titled “num Dec_Percent”ExampleDec_Percent demonstrates percentage calculations
Code
func ExampleDec_Percent() { // Calculate percentage value := MustDecFromString("850.00") percentage := MustDecFromString("15") // 15%
percentValue := value.ApplyPercent(percentage) finalValue := value.AddPercent(percentage)
fmt.Printf("Original value: %s\n", value.String()) fmt.Printf("Percentage: %s%%\n", percentage.String()) fmt.Printf("Percentage amount: %s\n", percentValue.String()) fmt.Printf("Final value (with percentage): %s\n", finalValue.String())
// Output: // Original value: 850 // Percentage: 15% // Percentage amount: 127.5 // Final value (with percentage): 977.5}[⬆️ Back to Top]!(#table-of-contents)
num Dec_Round
Section titled “num Dec_Round”ExampleDec_Round demonstrates decimal rounding
Code
func ExampleDec_Round() { // Round to different precision levels value := MustDecFromString("123.456789")
rounded2 := value.RoundTo(2) rounded4 := value.RoundTo(4) rounded0 := value.RoundTo(0)
fmt.Printf("Original: %s\n", value.String()) fmt.Printf("Rounded to 2 decimals: %s\n", rounded2.String()) fmt.Printf("Rounded to 4 decimals: %s\n", rounded4.String()) fmt.Printf("Rounded to 0 decimals: %s\n", rounded0.String())
// Output: // Original: 123.456789 // Rounded to 2 decimals: 123.46 // Rounded to 4 decimals: 123.4568 // Rounded to 0 decimals: 123}[⬆️ Back to Top]!(#table-of-contents)
num Dec_Sub
Section titled “num Dec_Sub”ExampleDec_Sub demonstrates decimal subtraction
Code
func ExampleDec_Sub() { // Perform decimal subtraction balance := MustDecFromString("1000.00") withdrawal := MustDecFromString("750.25")
remaining := balance.Sub(withdrawal)
fmt.Printf("Initial balance: %s\n", balance.String()) fmt.Printf("Withdrawal: %s\n", withdrawal.String()) fmt.Printf("Remaining: %s\n", remaining.String())
// Output: // Initial balance: 1000 // Withdrawal: 750.25 // Remaining: 249.75}[⬆️ Back to Top]!(#table-of-contents)
num MustDecFromAny
Section titled “num MustDecFromAny”ExampleMustDecFromAny demonstrates creating a decimal from any supported type
Code
func ExampleMustDecFromAny() { // Create decimals from different types fromInt := MustDecFromAny(100) fromFloat := MustDecFromAny(3.14159) fromString := MustDecFromAny("42.42")
fmt.Printf("From int: %s\n", fromInt.String()) fmt.Printf("From float: %s\n", fromFloat.String()) fmt.Printf("From string: %s\n", fromString.String())
// Output: // From int: 100 // From float: 3.14159 // From string: 42.42}[⬆️ Back to Top]!(#table-of-contents)
num MustDecFromString
Section titled “num MustDecFromString”ExampleMustDecFromString demonstrates creating a decimal from a string (panics on error)
Code
func ExampleMustDecFromString() { // Create decimal from valid string price := MustDecFromString("999.99")
fmt.Printf("Price: %s\n", price.String()) if f, ok := price.Float64(); ok { fmt.Printf("As float: %.2f\n", f) }
// Output: // Price: 999.99}[⬆️ Back to Top]!(#table-of-contents)
num NewDecFromFloat
Section titled “num NewDecFromFloat”ExampleNewDecFromFloat demonstrates creating a decimal from a float
Code
func ExampleNewDecFromFloat() { // Create decimal from float temperature := NewDecFromFloat(36.5)
fmt.Printf("Temperature: %s\n", temperature.String()) if f, ok := temperature.Float64(); ok { fmt.Printf("As float: %.1f\n", f) } fmt.Printf("Number of decimals: %d\n", temperature.NumberOfDecimals())
// Output: // Temperature: 36.5 // As float: 36.5 // Number of decimals: 1}[⬆️ Back to Top]!(#table-of-contents)
num NewDecFromInt
Section titled “num NewDecFromInt”ExampleNewDecFromInt demonstrates creating a decimal from an integer
Code
func ExampleNewDecFromInt() { // Create decimal from integer quantity := NewDecFromInt(42)
fmt.Printf("Quantity: %s\n", quantity.String()) fmt.Printf("As int: %d\n", quantity.IntPart()) fmt.Printf("Is zero: %t\n", quantity.IsZero())
// Output: // Quantity: 42 // As int: 42 // Is zero: false}[⬆️ Back to Top]!(#table-of-contents)
num NewDecFromString
Section titled “num NewDecFromString”ExampleNewDecFromString demonstrates creating a decimal from a string
Code
func ExampleNewDecFromString() { // Create decimal from string price, err := NewDecFromString("123.456") if err != nil { fmt.Printf("Error: %v\n", err) return }
fmt.Printf("Price: %s\n", price.String()) fmt.Printf("Is set: %t\n", price.Isset())
// Try with invalid string _, err = NewDecFromString("invalid") fmt.Printf("Invalid string error: %v\n", err != nil)
// Output: // Price: 123.456 // Is set: true // Invalid string error: true}[⬆️ Back to Top]!(#table-of-contents)
[⬆️ Back to Top]!(#table-of-contents)
⛓️ Slices
Section titled “⛓️ Slices”Package slices provides a comprehensive set of generic utility functions for working with slices. It offers a functional approach to common slice operations such as transforming, filtering, searching, and manipulating elements in a type-safe manner.
Functions
Section titled “Functions”- [All]!(#slices-all)
- [Contains]!(#slices-contains)
- [Filter]!(#slices-filter)
- [FilterMap]!(#slices-filtermap)
- [Find]!(#slices-find)
- [Fold]!(#slices-fold)
- [Map]!(#slices-map)
- [Reduce]!(#slices-reduce)
- [Some]!(#slices-some)
- [ToMap]!(#slices-tomap)
- [Uniq]!(#slices-uniq)
- [UniqFn]!(#slices-uniqfn)
- [UniqSorted]!(#slices-uniqsorted)
- [UniqSortedFn]!(#slices-uniqsortedfn)
slices All
Section titled “slices All”ExampleAll demonstrates checking if all elements satisfy a condition.
Code
func ExampleAll() { // Create a slice of positive numbers numbers := []int{1, 2, 3, 4, 5}
// Check if all numbers are positive allPositive := All(numbers, func(n int) bool { return n > 0 })
// Check if all numbers are even allEven := All(numbers, func(n int) bool { return n%2 == 0 })
fmt.Printf("All positive: %t\n", allPositive) fmt.Printf("All even: %t\n", allEven) // Output: // All positive: true // All even: false}[⬆️ Back to Top]!(#table-of-contents)
slices Contains
Section titled “slices Contains”ExampleContains demonstrates checking if any element satisfies a condition.
Code
func ExampleContains() { // Create a slice of numbers numbers := []int{1, 2, 3, 4, 5}
// Check if any number is greater than 3 hasLarge := Contains(numbers, func(n int) bool { return n > 3 })
// Check if any number is negative hasNegative := Contains(numbers, func(n int) bool { return n < 0 })
fmt.Printf("Has number > 3: %t\n", hasLarge) fmt.Printf("Has negative: %t\n", hasNegative) // Output: // Has number > 3: true // Has negative: false}[⬆️ Back to Top]!(#table-of-contents)
slices Filter
Section titled “slices Filter”ExampleFilter demonstrates filtering a slice to keep only elements that satisfy a condition.
Code
func ExampleFilter() { // Create a slice of numbers numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// Filter to keep only even numbers evenNumbers := Filter(numbers, func(n int) bool { return n%2 == 0 })
fmt.Println(evenNumbers) // Output: [2 4 6 8 10]}[⬆️ Back to Top]!(#table-of-contents)
slices FilterMap
Section titled “slices FilterMap”ExampleFilterMap demonstrates filtering and transforming in a single operation.
Code
func ExampleFilterMap() { // Create a slice of numbers numbers := []int{1, 2, 3, 4, 5, 6}
// Keep only even numbers and square them evenSquares := FilterMap(numbers, func(n int) fp.Option[int] { if n%2 == 0 { return fp.Some(n * n) } return fp.None[int]!() })
fmt.Println(evenSquares) // Output: [4 16 36]}[⬆️ Back to Top]!(#table-of-contents)
slices Find
Section titled “slices Find”ExampleFind demonstrates finding the first element that matches a condition.
Code
func ExampleFind() { // Create a slice of names names := []string{"Alice", "Bob", "Charlie", "David"}
// Find the first name that starts with 'C' result, found := Find(names, func(name string) bool { return len(name) > 0 && name[0] == 'C' })
fmt.Printf("Found: %t, Name: %s\n", found, result) // Output: Found: true, Name: Charlie}[⬆️ Back to Top]!(#table-of-contents)
slices Fold
Section titled “slices Fold”ExampleFold demonstrates folding a slice with an initial value.
Code
func ExampleFold() { // Create a slice of strings words := []string{"Hello", "World", "from", "Go"}
// Join with custom separator and prefix result := Fold(words, func(acc, word string) string { if acc == "" { return "Greeting: " + word } return acc + " " + word }, "")
fmt.Printf("Result: %s\n", result) // Output: // Result: Greeting: Hello World from Go}[⬆️ Back to Top]!(#table-of-contents)
slices Map
Section titled “slices Map”ExampleMap demonstrates transforming elements in a slice.
Code
func ExampleMap() { // Create a slice of numbers numbers := []int{1, 2, 3, 4, 5}
// Transform each number by squaring it squares := Map(numbers, func(n int) int { return n * n })
fmt.Println(squares) // Output: [1 4 9 16 25]}[⬆️ Back to Top]!(#table-of-contents)
slices Reduce
Section titled “slices Reduce”ExampleReduce demonstrates combining all elements into a single value.
Code
func ExampleReduce() { // Create a slice of numbers numbers := []int{1, 2, 3, 4, 5}
// Sum all numbers sum := Reduce[int, int]!(numbers, func(acc, curr int) int { return acc + curr })
fmt.Println(sum) // Output: 15}[⬆️ Back to Top]!(#table-of-contents)
slices Some
Section titled “slices Some”ExampleSome demonstrates checking if some elements satisfy a condition.
Code
func ExampleSome() { // Create a slice of words words := []string{"hello", "world", "go", "programming"}
// Check if some words are short (< 4 characters) hasShort := Some(words, func(word string) bool { return len(word) < 4 })
fmt.Printf("Has short words: %t\n", hasShort) // Output: // Has short words: true}[⬆️ Back to Top]!(#table-of-contents)
slices ToMap
Section titled “slices ToMap”ExampleToMap demonstrates converting a slice to a map using a key function.
Code
func ExampleToMap() { // Create a slice of words words := []string{"apple", "banana", "cherry"}
// Convert to map with first letter as key wordMap := ToMap(words, func(word string) rune { return rune(word[0]) })
fmt.Printf("'a' word: %s\n", wordMap['a']) fmt.Printf("'b' word: %s\n", wordMap['b']) // Output: // 'a' word: apple // 'b' word: banana}[⬆️ Back to Top]!(#table-of-contents)
slices Uniq
Section titled “slices Uniq”ExampleUniq demonstrates removing duplicate elements from a slice.
Code
func ExampleUniq() { // Create a slice with duplicate elements numbers := []int{1, 2, 2, 3, 3, 3, 4, 5, 5}
// Remove duplicates unique := Uniq(numbers)
fmt.Printf("Original: %v\n", numbers) fmt.Printf("Unique: %v\n", unique) // Output: // Original: [1 2 2 3 3 3 4 5 5] // Unique: [1 2 3 4 5]}[⬆️ Back to Top]!(#table-of-contents)
slices UniqFn
Section titled “slices UniqFn”ExampleUniqFn demonstrates removing duplicates using a custom equality function.
Code
func ExampleUniqFn() { type person struct { name string age int }
// Create a slice with people having duplicate names people := []person{ {"Alice", 25}, {"Bob", 30}, {"Alice", 40}, // duplicate name {"Carol", 35}, {"Bob", 50}, // duplicate name }
// Remove duplicates by name uniqueByName := UniqFn(people, func(a, b person) bool { return a.name == b.name })
fmt.Printf("Original count: %d\n", len(people)) fmt.Printf("Unique by name count: %d\n", len(uniqueByName)) for _, p := range uniqueByName { fmt.Printf(" %s (%d)\n", p.name, p.age) } // Output: // Original count: 5 // Unique by name count: 3 // Alice (25) // Bob (30) // Carol (35)}[⬆️ Back to Top]!(#table-of-contents)
slices UniqSorted
Section titled “slices UniqSorted”ExampleUniqSorted demonstrates removing consecutive duplicate elements from a sorted slice.
Code
func ExampleUniqSorted() { // Create a sorted slice with consecutive duplicate elements sortedNumbers := []int{1, 2, 2, 3, 3, 3, 4, 5, 5}
// Remove consecutive duplicates unique := UniqSorted(sortedNumbers)
fmt.Printf("Original sorted: %v\n", sortedNumbers) fmt.Printf("Unique: %v\n", unique) // Output: // Original sorted: [1 2 2 3 3 3 4 5 5] // Unique: [1 2 3 4 5]}[⬆️ Back to Top]!(#table-of-contents)
slices UniqSortedFn
Section titled “slices UniqSortedFn”ExampleUniqSortedFn demonstrates removing consecutive duplicates using a custom equality function.
Code
func ExampleUniqSortedFn() { type person struct { name string age int }
// Create a slice sorted by name with consecutive duplicates sortedPeople := []person{ {"Alice", 25}, {"Alice", 40}, // consecutive duplicate name {"Bob", 30}, {"Bob", 50}, // consecutive duplicate name {"Carol", 35}, }
// Remove consecutive duplicates by name uniqueByName := UniqSortedFn(sortedPeople, func(a, b person) bool { return a.name == b.name })
fmt.Printf("Original count: %d\n", len(sortedPeople)) fmt.Printf("Unique by name count: %d\n", len(uniqueByName)) for _, p := range uniqueByName { fmt.Printf(" %s (%d)\n", p.name, p.age) } // Output: // Original count: 5 // Unique by name count: 3 // Alice (25) // Bob (30) // Carol (35)}[⬆️ Back to Top]!(#table-of-contents)
[⬆️ Back to Top]!(#table-of-contents)
🌊 Streams
Section titled “🌊 Streams”Package streams provides interfaces and types for reading and writing streams of data.
Functions
Section titled “Functions”- [Batch]!(#streams-batch)
- [CSV]!(#streams-csv)
- [CSVTransform]!(#streams-csvtransform)
- [CSVTransform_tabSeparated]!(#streams-csvtransform_tabseparated)
- [ConsumeErrSkip]!(#streams-consumeerrskip)
- [DB]!(#streams-db)
- [Filter]!(#streams-filter)
- [FilterMap]!(#streams-filtermap)
- [Flatten]!(#streams-flatten)
- [Group]!(#streams-group)
- [JSON]!(#streams-json)
- [JSONEachRowTransform]!(#streams-jsoneachrowtransform)
- [JSONTransform]!(#streams-jsontransform)
- [Lines]!(#streams-lines)
- [Map]!(#streams-map)
- [MemWriter]!(#streams-memwriter)
- [Multicast]!(#streams-multicast)
- [Pipe]!(#streams-pipe)
- [PipeCSV]!(#streams-pipecsv)
- [PipeJSON]!(#streams-pipejson)
- [PipeJSONEachRow]!(#streams-pipejsoneachrow)
- [Reader]!(#streams-reader)
- [Reduce]!(#streams-reduce)
- [ReduceMap]!(#streams-reducemap)
- [ReduceSlice]!(#streams-reduceslice)
- [WriteAll]!(#streams-writeall)
streams Batch
Section titled “streams Batch”ExampleBatch demonstrates grouping stream elements into batches.
Code
func ExampleBatch() { // Create a stream from a slice of integers data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} stream := MemReader(data, nil)
// Group into batches of 3 batchStream := Batch(stream, 3)
// Collect the results result, _ := Consume(batchStream) for i, batch := range result { fmt.Printf("Batch %d: %v\n", i+1, batch) } // Output: // Batch 1: [1 2 3] // Batch 2: [4 5 6] // Batch 3: [7 8 9] // Batch 4: [10]}[⬆️ Back to Top]!(#table-of-contents)
streams CSV
Section titled “streams CSV”ExampleCSV demonstrates reading CSV data from a string.
Code
func ExampleCSV() { // Create a CSV reader from a string csvData := "name,age,city\nAlice,25,NYC\nBob,30,LA\nCharlie,35,Chicago" reader := io.NopCloser(strings.NewReader(csvData))
// Create a CSV stream directly csvStream, _ := CSV[[]string]!( WithCSVReader(reader), WithCSVSeparator(","), )
// Collect the results result, _ := Consume(csvStream) for i, row := range result { fmt.Printf("Row %d: %v\n", i+1, row) } // Output: // Row 1: [name age city] // Row 2: [Alice 25 NYC] // Row 3: [Bob 30 LA] // Row 4: [Charlie 35 Chicago]}[⬆️ Back to Top]!(#table-of-contents)
streams CSVTransform
Section titled “streams CSVTransform”ExampleCSVTransform demonstrates converting a stream to CSV format.
Code
func ExampleCSVTransform() { // Create a stream of employees employees := []Employee{ {ID: 1, Name: "Alice Johnson", Department: "Engineering", Salary: 75000.00}, {ID: 2, Name: "Bob Smith", Department: "Marketing", Salary: 65000.00}, {ID: 3, Name: "Charlie Brown", Department: "Engineering", Salary: 80000.00}, } stream := MemReader(employees, nil)
// Transform to CSV with comma separator transform := CSVTransform(stream, CSVSeparatorComma) transform.WriteTo(os.Stdout)
// Output: // ID,Name,Department,Salary // 1,Alice Johnson,Engineering,75000.00 // 2,Bob Smith,Marketing,65000.00 // 3,Charlie Brown,Engineering,80000.00}[⬆️ Back to Top]!(#table-of-contents)
streams CSVTransform_tabSeparated
Section titled “streams CSVTransform_tabSeparated”ExampleCSVTransform_tabSeparated demonstrates CSV with tab separator.
Code
func ExampleCSVTransform_tabSeparated() {
// Create a stream of products products := []ProductCSV{ {SKU: "LAPTOP-001", Name: "Gaming Laptop", Price: 1299.99}, {SKU: "MOUSE-002", Name: "Wireless Mouse", Price: 49.99}, {SKU: "KEYBOARD-003", Name: "Mechanical Keyboard", Price: 129.99}, } stream := MemReader(products, nil)
// Transform to CSV with tab separator transform := CSVTransform(stream, CSVSeparatorTab) transform.WriteTo(os.Stdout)
// Output: // SKU Product Name Price // LAPTOP-001 Gaming Laptop $1299.99 // MOUSE-002 Wireless Mouse $49.99 // KEYBOARD-003 Mechanical Keyboard $129.99}[⬆️ Back to Top]!(#table-of-contents)
streams ConsumeErrSkip
Section titled “streams ConsumeErrSkip”ExampleConsumeErrSkip demonstrates consuming a stream while skipping errors.
Code
func ExampleConsumeErrSkip() { // Create a filter stream that may produce errors reader := strings.NewReader("1\n2\ninvalid\n4\n5") numbersStream := Lines(reader)
// Create a filter that converts strings to numbers (may fail) filterStream := FilterMap(numbersStream, func(s string) (int, bool) { // Simulate conversion that might fail if s == "invalid" { return 0, false // This will be skipped } // Simple conversion for demonstration switch s { case "1": return 1, true case "2": return 2, true case "4": return 4, true case "5": return 5, true default: return 0, false } })
// Consume all valid numbers, skipping errors numbers := ConsumeErrSkip(filterStream)
fmt.Printf("Valid numbers: %v\n", numbers)
// Output: // Valid numbers: [1 2 4 5]}[⬆️ Back to Top]!(#table-of-contents)
streams DB
Section titled “streams DB”ExampleDB demonstrates how to use DB with database rows.
Code
func ExampleDB() { // Mock data that simulates database rows mockData := &mockRows{ data: [][]any{ {1, "Alice"}, {2, "Bob"}, {3, "Charlie"}, }, }
// Create a stream with a scan function stream := DB(mockData, func(rows DBRows, user *User) error { return rows.Scan(&user.ID, &user.Name) })
// Iterate through the stream for stream.Next() { user := stream.Data() fmt.Printf("User ID: %d, Name: %s\n", user.ID, user.Name) }
// Check for errors if err := stream.Err(); err != nil { log.Printf("Error during streaming: %v", err) }
// Output: // User ID: 1, Name: Alice // User ID: 2, Name: Bob // User ID: 3, Name: Charlie}[⬆️ Back to Top]!(#table-of-contents)
streams Filter
Section titled “streams Filter”ExampleFilter demonstrates filtering a stream of integers to keep only even numbers.
Code
func ExampleFilter() { // Create a stream from a slice of integers data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} stream := MemReader(data, nil)
// Filter to keep only even numbers evenStream := Filter(stream, func(n int) bool { return n%2 == 0 })
// Collect the results result, _ := Consume(evenStream) fmt.Println(result) // Output: [2 4 6 8 10]}[⬆️ Back to Top]!(#table-of-contents)
streams FilterMap
Section titled “streams FilterMap”ExampleFilterMap demonstrates filtering and transforming in a single operation.
Code
func ExampleFilterMap() { // Create a stream from a slice of integers data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} stream := MemReader(data, nil)
// Filter even numbers and convert them to strings evenStrings := FilterMap(stream, func(n int) (string, bool) { if n%2 == 0 { return strconv.Itoa(n), true } return "", false })
// Collect the results result, _ := Consume(evenStrings) fmt.Println(result) // Output: [2 4 6 8 10]}[⬆️ Back to Top]!(#table-of-contents)
streams Flatten
Section titled “streams Flatten”ExampleFlatten demonstrates flattening a stream of slices.
Code
func ExampleFlatten() { // Create a stream from a slice of slices data := [][]int{{1, 2}, {3, 4, 5}, {6}, {7, 8, 9}} stream := MemReader(data, nil)
// Flatten the slices flattened := Flatten(stream)
// Collect the results result, _ := Consume(flattened) fmt.Println(result) // Output: [1 2 3 4 5 6 7 8 9]}[⬆️ Back to Top]!(#table-of-contents)
streams Group
Section titled “streams Group”ExampleGroup demonstrates grouping consecutive items with the same key.
Code
func ExampleGroup() { // Create a stream from a slice of strings data := []string{"apple", "apricot", "banana", "blueberry", "cherry", "coconut"} stream := MemReader(data, nil)
// Group by first letter Grouped := Group(stream, func(s string) rune { return rune(s[0]) })
// Collect the results result, _ := Consume(Grouped) for _, group := range result { fmt.Printf("Group: %v\n", group) } // Output: // Group: [apple apricot] // Group: [banana blueberry] // Group: [cherry coconut]}[⬆️ Back to Top]!(#table-of-contents)
streams JSON
Section titled “streams JSON”ExampleJSON demonstrates reading JSON data line by line.
Code
func ExampleJSON() { // Create JSON-lines data (each line is a separate JSON object) jsonData := `{"name":"Alice","age":25} {"name":"Bob","age":30} {"name":"Charlie","age":35}`
reader := strings.NewReader(jsonData)
// Create a JSON stream for a simple struct type Person struct { Name string `json:"name"` Age int `json:"age"` }
jsonStream := JSON[Person]!(io.NopCloser(reader))
// Collect the results result, _ := Consume(jsonStream) for _, person := range result { fmt.Printf("Person: %s, Age: %d\n", person.Name, person.Age) } // Output: // Person: Alice, Age: 25 // Person: Bob, Age: 30 // Person: Charlie, Age: 35}[⬆️ Back to Top]!(#table-of-contents)
streams JSONEachRowTransform
Section titled “streams JSONEachRowTransform”ExampleJSONEachRowTransform demonstrates converting a stream to JSON lines format.
Code
func ExampleJSONEachRowTransform() { // Define a simple structure for demonstration type LogEntry struct { Timestamp string `json:"timestamp"` Level string `json:"level"` Message string `json:"message"` }
// Create a stream of log entries logs := []LogEntry{ {Timestamp: "2025-06-28T10:00:00Z", Level: "INFO", Message: "Application started"}, {Timestamp: "2025-06-28T10:01:00Z", Level: "WARN", Message: "High memory usage detected"}, {Timestamp: "2025-06-28T10:02:00Z", Level: "ERROR", Message: "Database connection failed"}, } stream := MemReader(logs, nil)
// Transform to JSON lines format and write to stdout transform := JSONEachRowTransform(stream) transform.WriteTo(os.Stdout)
// Output: // {"timestamp":"2025-06-28T10:00:00Z","level":"INFO","message":"Application started"} // {"timestamp":"2025-06-28T10:01:00Z","level":"WARN","message":"High memory usage detected"} // {"timestamp":"2025-06-28T10:02:00Z","level":"ERROR","message":"Database connection failed"}}[⬆️ Back to Top]!(#table-of-contents)
streams JSONTransform
Section titled “streams JSONTransform”ExampleJSONTransform demonstrates converting a stream to JSON array format.
Code
func ExampleJSONTransform() { // Define a simple structure for demonstration type Person struct { ID int `json:"id"` Name string `json:"name"` }
// Create a stream from a slice of persons people := []Person{ {ID: 1, Name: "Alice"}, {ID: 2, Name: "Bob"}, {ID: 3, Name: "Charlie"}, } stream := MemReader(people, nil)
// Transform to JSON and write to stdout transform := JSONTransform(stream) transform.WriteTo(os.Stdout)
// Output: // [{"id":1,"name":"Alice"},{"id":2,"name":"Bob"},{"id":3,"name":"Charlie"}]}[⬆️ Back to Top]!(#table-of-contents)
streams Lines
Section titled “streams Lines”ExampleLines demonstrates reading lines from a string.
Code
func ExampleLines() { // Create a reader from a multiline string text := "line1\nline2\nline3\n" reader := strings.NewReader(text)
// Create a lines stream lineStream := Lines(reader)
// Collect the results result, _ := Consume(lineStream) fmt.Println(result) // Output: [line1 line2 line3]}[⬆️ Back to Top]!(#table-of-contents)
streams Map
Section titled “streams Map”ExampleMap demonstrates transforming elements in a stream.
Code
func ExampleMap() { // Create a stream from a slice of integers data := []int{1, 2, 3, 4, 5} stream := MemReader(data, nil)
// Transform integers to their string representation stringStream := Map(stream, func(n int) string { return fmt.Sprintf("number_%d", n) })
// Collect the results result, _ := Consume(stringStream) fmt.Println(result) // Output: [number_1 number_2 number_3 number_4 number_5]}[⬆️ Back to Top]!(#table-of-contents)
streams MemWriter
Section titled “streams MemWriter”ExampleMemWriter demonstrates writing items to memory.
Code
func ExampleMemWriter() { // Create a memory writer for strings writer := MemWriter[string]!()
// Write some items items := []string{"hello", "world", "from", "memory"} for _, item := range items { writer.Write(item) }
// Get all items result := writer.Items()
fmt.Printf("Items written: %d\n", len(result)) fmt.Printf("Items: %v\n", result) // Output: // Items written: 4 // Items: [hello world from memory]}[⬆️ Back to Top]!(#table-of-contents)
streams Multicast
Section titled “streams Multicast”ExampleMulticast demonstrates broadcasting a stream to multiple destinations.
Code
func ExampleMulticast() { // Create a stream of numbers reader := strings.NewReader("1\n2\n3\n4\n5") source := Lines(reader)
// Create two memory writers to collect data separately dest1 := MemWriter[string]!() dest2 := MemWriter[string]!()
// Multicast the stream to both destinations counts, err := Multicast(source, dest1, dest2) if err != nil { fmt.Printf("Error: %v\n", err) return }
fmt.Printf("Written to dest1: %d items\n", counts[0]) fmt.Printf("Written to dest2: %d items\n", counts[1]) fmt.Printf("Dest1 data: %v\n", dest1.Items()) fmt.Printf("Dest2 data: %v\n", dest2.Items())
// Output: // Written to dest1: 5 items // Written to dest2: 5 items // Dest1 data: [1 2 3 4 5] // Dest2 data: [1 2 3 4 5]}[⬆️ Back to Top]!(#table-of-contents)
streams Pipe
Section titled “streams Pipe”ExamplePipe demonstrates piping data from one stream to another.
Code
func ExamplePipe() { // Create a source stream data := []string{"hello", "world", "from", "streams"} source := MemReader(data, nil)
// Create a destination dest := MemWriter[string]!()
// Pipe data from source to destination bytesWritten, _ := Pipe(source, dest)
fmt.Printf("Items written: %d\n", bytesWritten) fmt.Printf("Items: %v\n", dest.Items()) // Output: // Items written: 4 // Items: [hello world from streams]}[⬆️ Back to Top]!(#table-of-contents)
streams PipeCSV
Section titled “streams PipeCSV”ExamplePipeCSV demonstrates using the PipeCSV convenience function.
Code
func ExamplePipeCSV() { // Create a stream of employees employees := []Employee{ {ID: 101, Name: "Diana Prince", Department: "Legal", Salary: 90000.00}, {ID: 102, Name: "Clark Kent", Department: "Journalism", Salary: 55000.00}, } stream := MemReader(employees, nil)
// Use PipeCSV to write directly to stdout with comma separator rowsWritten, err := PipeCSV(stream, os.Stdout, CSVSeparatorComma) if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Rows written: %d\n", rowsWritten)
// Output: // ID,Name,Department,Salary // 101,Diana Prince,Legal,90000.00 // 102,Clark Kent,Journalism,55000.00 // Rows written: 3}[⬆️ Back to Top]!(#table-of-contents)
streams PipeJSON
Section titled “streams PipeJSON”ExamplePipeJSON demonstrates using the PipeJSON convenience function.
Code
func ExamplePipeJSON() { // Define a simple structure type Product struct { ID int `json:"id"` Name string `json:"name"` Price float64 `json:"price"` }
// Create a stream of products products := []Product{ {ID: 1, Name: "Laptop", Price: 999.99}, {ID: 2, Name: "Mouse", Price: 29.99}, } stream := MemReader(products, nil)
// Use PipeJSON to write directly to stdout bytesWritten, err := PipeJSON(stream, os.Stdout) if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("\nBytes written: %d\n", bytesWritten)
// Output: // [{"id":1,"name":"Laptop","price":999.99},{"id":2,"name":"Mouse","price":29.99}] // Bytes written: 79}[⬆️ Back to Top]!(#table-of-contents)
streams PipeJSONEachRow
Section titled “streams PipeJSONEachRow”ExamplePipeJSONEachRow demonstrates using the PipeJSONEachRow convenience function.
Code
func ExamplePipeJSONEachRow() { // Define a simple metric structure type Metric struct { Name string `json:"name"` Value float64 `json:"value"` Unit string `json:"unit"` }
// Create a stream of metrics metrics := []Metric{ {Name: "cpu_usage", Value: 85.5, Unit: "percent"}, {Name: "memory_usage", Value: 1024, Unit: "MB"}, {Name: "disk_usage", Value: 75.2, Unit: "percent"}, } stream := MemReader(metrics, nil)
// Use PipeJSONEachRow to write to stdout bytesWritten, err := PipeJSONEachRow(stream, os.Stdout) if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Bytes written: %d\n", bytesWritten)
// Output: // {"name":"cpu_usage","value":85.5,"unit":"percent"} // {"name":"memory_usage","value":1024,"unit":"MB"} // {"name":"disk_usage","value":75.2,"unit":"percent"} // Bytes written: 152}[⬆️ Back to Top]!(#table-of-contents)
streams Reader
Section titled “streams Reader”ExampleReader demonstrates reading byte chunks from an io.Reader.
Code
func ExampleReader() { // Create data to read data := "line1\nline2\nline3\n" reader := strings.NewReader(data)
// Create a byte stream stream := Reader(reader)
// Read all chunks var chunks []string for stream.Next() { chunks = append(chunks, string(stream.Data())) }
fmt.Printf("Chunks: %d\n", len(chunks)) fmt.Printf("First chunk: %q\n", chunks[0]) // Output: // Chunks: 3 // First chunk: "line1\n"}[⬆️ Back to Top]!(#table-of-contents)
streams Reduce
Section titled “streams Reduce”ExampleReduce demonstrates using Reduce to sum numbers from a stream.
Code
func ExampleReduce() { // Create a stream of numbers from strings reader := strings.NewReader("10\n20\n30\n40\n50") lines := Lines(reader)
// Convert strings to numbers and sum them sum, _ := Reduce(Map(lines, func(s string) int { n, _ := strconv.Atoi(s) return n }), func(acc, n int) int { return acc + n }, 0)
fmt.Printf("Sum: %d\n", sum)
// Output: // Sum: 150}[⬆️ Back to Top]!(#table-of-contents)
streams ReduceMap
Section titled “streams ReduceMap”ExampleReduceMap demonstrates reducing a stream to a map with aggregated values.
Code
func ExampleReduceMap() { // Create a stream of words reader := strings.NewReader("apple\nbanana\napple\ncherry\nbanana\napple") stream := Lines(reader)
// Count occurrences of each word counts, _ := ReduceMap(stream, func(acc map[string]int, word string) map[string]int { acc[word]++ return acc })
fmt.Printf("apple: %d\n", counts["apple"]) fmt.Printf("banana: %d\n", counts["banana"]) fmt.Printf("cherry: %d\n", counts["cherry"])
// Output: // apple: 3 // banana: 2 // cherry: 1}[⬆️ Back to Top]!(#table-of-contents)
streams ReduceSlice
Section titled “streams ReduceSlice”ExampleReduceSlice demonstrates collecting filtered items from a stream.
Code
func ExampleReduceSlice() { // Create a stream of words reader := strings.NewReader("cat\ndog\nelephant\nant\nbutterfly\nbird") stream := Lines(reader)
// Collect only words longer than 3 characters longWords, _ := ReduceSlice(stream, func(acc []string, word string) []string { if len(word) > 3 { return append(acc, word) } return acc })
fmt.Printf("Long words: %v\n", longWords)
// Output: // Long words: [elephant butterfly bird]}[⬆️ Back to Top]!(#table-of-contents)
streams WriteAll
Section titled “streams WriteAll”ExampleWriteAll demonstrates writing a slice to a stream.
Code
func ExampleWriteAll() { // Create data to write data := []string{"hello", "world", "streams"}
// Create a memory writer writer := MemWriter[string]!()
// Write all data bytesWritten, err := WriteAll(writer, data) if err != nil { fmt.Printf("Error: %v\n", err) return }
fmt.Printf("Bytes written: %d\n", bytesWritten) fmt.Printf("Items: %v\n", writer.Items()) // Output: // Bytes written: 3 // Items: [hello world streams]}[⬆️ Back to Top]!(#table-of-contents)
[⬆️ Back to Top]!(#table-of-contents)
🔞 Zero
Section titled “🔞 Zero”Zero-value utilities and string manipulation functions.
Functions
Section titled “Functions”- [B2S]!(#zero-b2s)
- [S2B]!(#zero-s2b)
zero B2S
Section titled “zero B2S”ExampleB2S demonstrates converting []byte to string without memory allocation
Code
func ExampleB2S() { // Convert []byte to string using zero-allocation conversion b := []byte("Hello, Gophers!") s := B2S(b)
fmt.Printf("Original bytes: %v\n", b) fmt.Printf("Converted to string: %s\n", s) fmt.Printf("Length: %d\n", len(s)) fmt.Printf( "Same underlying data: %t\n", uintptr(unsafe.Pointer(&b[0])) == uintptr(unsafe.Pointer(unsafe.StringData(s))), )
// Output: // Original bytes: [72 101 108 108 111 44 32 71 111 112 104 101 114 115 33] // Converted to string: Hello, Gophers! // Length: 15 // Same underlying data: true}[⬆️ Back to Top]!(#table-of-contents)
zero S2B
Section titled “zero S2B”ExampleS2B demonstrates converting a string to []byte without memory allocation
Code
func ExampleS2B() { // Convert string to []byte using zero-allocation conversion s := "Hello, World!" b := S2B(s)
fmt.Printf("Original string: %s\n", s) fmt.Printf("Converted to bytes: %v\n", b) fmt.Printf("Bytes as string: %s\n", string(b)) fmt.Printf( "Same underlying data: %t\n", uintptr(unsafe.Pointer(unsafe.StringData(s))) == uintptr(unsafe.Pointer(&b[0])), )
// Output: // Original string: Hello, World! // Converted to bytes: [72 101 108 108 111 44 32 87 111 114 108 100 33] // Bytes as string: Hello, World! // Same underlying data: true}[⬆️ Back to Top]!(#table-of-contents)
[⬆️ Back to Top]!(#table-of-contents)