📖 View full documentation and examples on pkg.go.dev →
✨ Workspace Architecture
This project leverages Go workspaces to provide isolated dependencies for each module. This means:
- 🎯 Lightweight imports: When you import
fp
or streams
, you won't download database drivers or logging dependencies
- 🔧 Modular design: Each module (
db
, lol
, num
) maintains its own go.mod
with 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
Table of Contents
🗃️ Db
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 applied
err := 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
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)
}
⬆️ Back to Top
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)
}
⬆️ Back to Top
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)
}
⬆️ Back to Top
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
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)
}
⬆️ Back to Top
db In
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)
}
⬆️ Back to Top
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"))
}
⬆️ Back to Top
⬆️ Back to Top
Ent
Package ent provides utilities for managing environment variables in a type-safe manner.
Functions
ent Bool
ExampleBool demonstrates how to retrieve boolean environment variables with various true/false representations.
Code
func ExampleBool() {
os.Setenv("DEBUG", "true")
defer os.Unsetenv("DEBUG")
debug := Bool("DEBUG", false)
fmt.Println(debug)
}
⬆️ Back to Top
ent CondStrOrPanic
ExampleCondStrOrPanic demonstrates how to conditionally retrieve environment variables with panic on missing values.
Code
func ExampleCondStrOrPanic() {
os.Setenv("DEBUG_MODE", "true")
defer os.Unsetenv("DEBUG_MODE")
debugMode := CondStrOrPanic(true, "DEBUG_MODE")
fmt.Println(debugMode)
emptyValue := CondStrOrPanic(false, "DEBUG_MODE")
fmt.Println(emptyValue)
}
⬆️ Back to Top
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)
}
⬆️ Back to Top
ent Duration
ExampleDuration demonstrates how to retrieve time.Duration environment variables with fallback values.
Code
func ExampleDuration() {
os.Setenv("REQUEST_TIMEOUT", "30s")
defer os.Unsetenv("REQUEST_TIMEOUT")
timeout := Duration("REQUEST_TIMEOUT", 10*time.Second)
fmt.Println(timeout)
}
⬆️ Back to Top
ent Enum
ExampleEnum demonstrates how to retrieve environment variables with validation against allowed values.
Code
func ExampleEnum() {
os.Setenv("ENV", "staging")
defer os.Unsetenv("ENV")
env := Enum("ENV", "dev", "dev", "staging", "prod")
fmt.Println(env)
}
⬆️ Back to Top
ent EnumOrPanic
ExampleEnumOrPanic demonstrates how to retrieve required environment variables with validation against allowed values, panicking if invalid.
Code
func ExampleEnumOrPanic() {
os.Setenv("LOG_LEVEL", "info")
defer os.Unsetenv("LOG_LEVEL")
logLevel := EnumOrPanic("LOG_LEVEL", "debug", "info", "warn", "error")
fmt.Println(logLevel)
}
⬆️ Back to Top
ent FixedStrOrPanic
ExampleFixedStrOrPanic demonstrates how to retrieve environment variables with length validation.
Code
func ExampleFixedStrOrPanic() {
os.Setenv("API_KEY", "abc123")
defer os.Unsetenv("API_KEY")
apiKey := FixedStrOrPanic("API_KEY", 6)
fmt.Println(apiKey)
}
⬆️ Back to Top
ent Float64
ExampleFloat64 demonstrates how to retrieve float64 environment variables with fallback values.
Code
func ExampleFloat64() {
os.Setenv("PRICE", "19.99")
defer os.Unsetenv("PRICE")
price := Float64("PRICE", 0.0)
fmt.Println(price)
}
⬆️ Back to Top
ent Get
ExampleGet demonstrates how to retrieve environment variables with fallback values.
Code
func ExampleGet() {
os.Setenv("APP_NAME", "MyApplication")
defer os.Unsetenv("APP_NAME")
appName := Get("APP_NAME", "DefaultApp")
fmt.Println(appName)
dbHost := Get("DB_HOST", "localhost")
fmt.Println(dbHost)
}
⬆️ Back to Top
ent Int
ExampleInt demonstrates how to retrieve integer environment variables with fallback values.
Code
func ExampleInt() {
os.Setenv("WORKER_COUNT", "4")
defer os.Unsetenv("WORKER_COUNT")
workers := Int("WORKER_COUNT", 1)
fmt.Println(workers)
}
⬆️ Back to Top
ent Int64
ExampleInt64 demonstrates how to retrieve int64 environment variables with fallback values.
Code
func ExampleInt64() {
os.Setenv("MAX_CONNECTIONS", "100")
defer os.Unsetenv("MAX_CONNECTIONS")
maxConn := Int64("MAX_CONNECTIONS", 50)
fmt.Println(maxConn)
}
⬆️ Back to Top
ent Int64OrPanic
ExampleInt64OrPanic demonstrates how to retrieve required int64 environment variables that panic if missing or invalid.
Code
func ExampleInt64OrPanic() {
os.Setenv("PORT", "8080")
defer os.Unsetenv("PORT")
port := Int64OrPanic("PORT")
fmt.Println(port)
}
⬆️ Back to Top
ent IntOrPanic
ExampleIntOrPanic demonstrates how to retrieve required integer environment variables that panic if missing or invalid.
Code
func ExampleIntOrPanic() {
os.Setenv("TIMEOUT", "30")
defer os.Unsetenv("TIMEOUT")
timeout := IntOrPanic("TIMEOUT")
fmt.Println(timeout)
}
⬆️ Back to Top
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"`
}
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)
}
⬆️ Back to Top
ent SliceInt
ExampleSliceInt demonstrates how to retrieve integer slice environment variables from comma-separated values.
Code
func ExampleSliceInt() {
os.Setenv("PORTS", "8080,8081,8082")
defer os.Unsetenv("PORTS")
ports := SliceInt("PORTS", []int{3000})
fmt.Println(len(ports))
}
⬆️ Back to Top
ent SliceStr
ExampleSliceStr demonstrates how to retrieve string slice environment variables from comma-separated values.
Code
func ExampleSliceStr() {
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))
}
⬆️ Back to Top
ent Str
ExampleStr demonstrates how to retrieve string environment variables with fallback values.
Code
func ExampleStr() {
os.Setenv("USER_NAME", "john_doe")
defer os.Unsetenv("USER_NAME")
username := Str("USER_NAME", "anonymous")
fmt.Println(username)
}
⬆️ Back to Top
ent StrOrPanic
ExampleStrOrPanic demonstrates how to retrieve required environment variables that panic if missing.
Code
func ExampleStrOrPanic() {
os.Setenv("REQUIRED_CONFIG", "important_value")
defer os.Unsetenv("REQUIRED_CONFIG")
config := StrOrPanic("REQUIRED_CONFIG")
fmt.Println(config)
}
⬆️ Back to Top
⬆️ Back to Top
🪄 Fp
Functional programming utilities including Option and Result types.
Functions
fp Err
ExampleErr demonstrates creating an error Result.
Code
func ExampleErr() {
result := Err[string](errors.New("something failed"))
fmt.Printf("Is error: %t\n", result.IsErr())
fmt.Printf("Value: %s\n", result.UnwrapOr("default"))
}
⬆️ Back to Top
fp None
ExampleNone demonstrates creating an empty Option.
Code
func ExampleNone() {
empty := None[string]()
fmt.Printf("Has value: %t\n", empty.IsSome())
fmt.Printf("Value: %s\n", empty.UnwrapOr("default"))
}
⬆️ Back to Top
fp Ok
ExampleOk demonstrates creating a successful Result.
Code
func ExampleOk() {
result := Ok("Success!")
fmt.Printf("Is ok: %t\n", result.IsOk())
fmt.Printf("Value: %s\n", result.UnwrapOr("default"))
}
⬆️ Back to Top
fp OkZero
ExampleOkZero demonstrates creating a Result with zero value.
Code
func ExampleOkZero() {
result := OkZero[int]()
fmt.Printf("Is ok: %t\n", result.IsOk())
fmt.Printf("Value: %d\n", result.UnwrapOr(-1))
}
⬆️ Back to Top
fp Option
ExampleOption demonstrates basic usage of the Option type.
Code
func ExampleOption() {
someValue := Some(42)
noneValue := None[int]()
fmt.Printf("Some has value: %v\n", someValue.IsSome())
fmt.Printf("None has value: %v\n", noneValue.IsSome())
if value, ok := someValue.Unwrap(); ok {
fmt.Printf("Value: %d\n", value)
}
}
⬆️ Back to Top
fp OptionFromPtr
ExampleOptionFromPtr demonstrates creating Option from a pointer.
Code
func ExampleOptionFromPtr() {
value := "hello"
opt1 := OptionFromPtr(&value)
var nilPtr *string
opt2 := OptionFromPtr(nilPtr)
fmt.Printf("From pointer: %s\n", opt1.UnwrapOr("empty"))
fmt.Printf("From nil: %s\n", opt2.UnwrapOr("empty"))
}
⬆️ Back to Top
fp OptionFromTuple
ExampleOptionFromTuple demonstrates creating Option from a tuple pattern.
Code
func ExampleOptionFromTuple() {
getValue := func(key string) (string, bool) {
data := map[string]string{"name": "Alice", "age": "25"}
value, ok := data[key]
return value, ok
}
nameOpt := OptionFromTuple(getValue("name"))
missingOpt := OptionFromTuple(getValue("missing"))
fmt.Printf("Name: %s\n", nameOpt.UnwrapOr("unknown"))
fmt.Printf("Missing: %s\n", missingOpt.UnwrapOr("unknown"))
}
⬆️ Back to Top
fp Option_Map
ExampleOption_Map demonstrates transforming values inside Option.
Code
func ExampleOption_Map() {
maybeNumber := Some(5)
maybeSquare := maybeNumber.Map(func(x int) int { return x * x })
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))
}
⬆️ Back to Top
fp Option_Match
ExampleOption_Match demonstrates pattern matching with Option.
Code
func ExampleOption_Match() {
getValue := func(id int) Option[string] {
if id > 0 {
return Some(fmt.Sprintf("User_%d", id))
}
return None[string]()
}
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(""))
}
⬆️ Back to Top
fp Option_Or
ExampleOption_Or demonstrates providing fallback values.
Code
func ExampleOption_Or() {
primary := None[string]()
secondary := Some("backup")
tertiary := Some("fallback")
result := primary.Or(secondary).Or(tertiary)
fmt.Printf("Result: %s\n", result.UnwrapOr("default"))
}
⬆️ Back to Top
fp Result
ExampleResult demonstrates basic usage of the Result type.
Code
func ExampleResult() {
success := Ok("Hello, World!")
failure := Err[string](errors.New("something went wrong"))
fmt.Printf("Success is ok: %v\n", success.IsOk())
fmt.Printf("Failure is ok: %v\n", failure.IsOk())
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)
}
}
⬆️ Back to Top
fp Result_Map
ExampleResult_Map demonstrates transforming values inside Result.
Code
func ExampleResult_Map() {
result := Ok(5)
squared := result.Map(func(x int) int { return x * x })
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))
}
⬆️ Back to Top
fp Result_Match
ExampleResult_Match demonstrates pattern matching with Result.
Code
func ExampleResult_Match() {
divide := func(x, y int) Result[int] {
if y == 0 {
return Err[int](errors.New("division by zero"))
}
return Ok(x / y)
}
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())
}
⬆️ Back to Top
fp Result_Or
ExampleResult_Or demonstrates providing fallback results.
Code
func ExampleResult_Or() {
primary := Err[string](errors.New("primary failed"))
fallback := Ok("fallback value")
result := primary.Or(fallback)
fmt.Printf("Result: %s\n", result.UnwrapOr("default"))
}
⬆️ Back to Top
fp Some
ExampleSome demonstrates creating an Option with a value.
Code
func ExampleSome() {
message := Some("Hello, World!")
fmt.Printf("Has value: %t\n", message.IsSome())
fmt.Printf("Value: %s\n", message.UnwrapOr("default"))
}
⬆️ Back to Top
⬆️ Back to Top
📝 Lol
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
lol Logger_LogLevels
ExampleLogger_LogLevels demonstrates different log levels
Code
func ExampleLogger_LogLevels() {
var buf bytes.Buffer
logger := NewZerolog(
WithFields(Fields{"component": "auth"}),
WithEnv(EnvDev),
WithLevel(LevelTrace),
WithWriter(&buf),
)
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")),
)
}
⬆️ Back to Top
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),
)
enrichedLogger := logger.WithField("request_id", "req-123").
WithField("user_agent", "test-client")
enrichedLogger.Info("Processing request")
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")),
)
}
⬆️ Back to Top
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(),
)
tracer := apm.DefaultTracer()
tx := tracer.StartTransaction("payment-processing", "request")
defer tx.End()
ctx := apm.ContextWithTransaction(context.Background(), tx)
span, ctx := apm.StartSpan(ctx, "payment-validation", "internal")
defer span.End()
tracedLogger := logger.WithTrace(ctx)
tracedLogger.Info("Processing payment request")
tracedLogger.WithField("payment_id", "pay_123").
WithField("amount", 99.99).
Info("Payment validation started")
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")),
)
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")),
)
}
⬆️ Back to Top
lol NewZerolog
ExampleNewZerolog demonstrates creating a structured logger with zerolog backend
Code
func ExampleNewZerolog() {
var buf bytes.Buffer
logger := NewZerolog(
WithFields(Fields{"service": "example-app", "version": "1.0.0"}),
WithEnv(EnvProd),
WithLevel(LevelInfo),
WithWriter(&buf),
)
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")),
)
}
⬆️ Back to Top
⬆️ Back to Top
🗝️ 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
maps Equals
ExampleEquals demonstrates comparing two maps for equality.
Code
func ExampleEquals() {
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}
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)
}
⬆️ Back to Top
maps Filter
ExampleFilter demonstrates filtering a map by key-value pairs.
Code
func ExampleFilter() {
prices := map[string]int{
"apple": 100,
"banana": 50,
"cherry": 200,
"date": 75,
}
expensive := Filter(prices, func(product string, price int) bool {
return price > 75
})
fmt.Printf("Expensive items count: %d\n", len(expensive))
}
⬆️ Back to Top
maps FilterMap
ExampleFilterMap demonstrates filtering and transforming in a single operation.
Code
func ExampleFilterMap() {
ages := map[string]int{
"Alice": 25,
"Bob": 17,
"Carol": 30,
"Dave": 16,
}
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))
}
⬆️ Back to Top
maps FilterMapTuple
ExampleFilterMapTuple demonstrates filtering and transforming using tuple returns.
Code
func ExampleFilterMapTuple() {
scores := map[string]int{
"Alice": 85,
"Bob": 70,
"Carol": 95,
"Dave": 60,
}
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"])
}
⬆️ Back to Top
maps Fold
ExampleFold demonstrates folding a map with an initial value.
Code
func ExampleFold() {
prices := map[string]float64{
"apple": 1.20,
"banana": 0.80,
"cherry": 2.50,
}
totalWithTax := Fold(prices, func(acc float64, item string, price float64) float64 {
return acc + price*1.1
}, 5.0)
fmt.Printf("Total with tax: %.2f\n", totalWithTax)
}
⬆️ Back to Top
maps Map
ExampleMap demonstrates transforming keys and values in a map.
Code
func ExampleMap() {
numbers := map[int]string{
1: "one",
2: "two",
3: "three",
}
transformed := Map(numbers, func(key int, value string) (string, string) {
return fmt.Sprintf("num_%d", key), strings.ToUpper(value)
})
fmt.Println(transformed["num_1"])
}
⬆️ Back to Top
maps Reduce
ExampleReduce demonstrates reducing a map to a single value.
Code
func ExampleReduce() {
inventory := map[string]int{
"apples": 10,
"bananas": 5,
"oranges": 8,
}
total := Reduce(inventory, func(acc int, key string, value int) int {
return acc + value
})
fmt.Printf("Total items: %d\n", total)
}
⬆️ Back to Top
maps Slice
ExampleSlice demonstrates converting a map to a slice.
Code
func ExampleSlice() {
users := map[int]string{
1: "Alice",
2: "Bob",
3: "Carol",
}
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))
}
⬆️ Back to Top
⬆️ Back to Top
🔢 Num
Numeric utilities including high-precision decimal operations.
Functions
num Abs
ExampleAbs demonstrates absolute value calculation
Code
func ExampleAbs() {
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)
}
⬆️ Back to Top
num Dec_Add
ExampleDec_Add demonstrates decimal addition
Code
func ExampleDec_Add() {
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())
}
⬆️ Back to Top
num Dec_Compare
ExampleDec_Compare demonstrates decimal comparison
Code
func ExampleDec_Compare() {
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))
}
⬆️ Back to Top
num Dec_Div
ExampleDec_Div demonstrates decimal division
Code
func ExampleDec_Div() {
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())
}
⬆️ Back to Top
num Dec_IsZero
ExampleDec_IsZero demonstrates zero checking
Code
func ExampleDec_IsZero() {
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())
}
⬆️ Back to Top
num Dec_Mul
ExampleDec_Mul demonstrates decimal multiplication
Code
func ExampleDec_Mul() {
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())
}
⬆️ Back to Top
num Dec_Percent
ExampleDec_Percent demonstrates percentage calculations
Code
func ExampleDec_Percent() {
value := MustDecFromString("850.00")
percentage := MustDecFromString("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())
}
⬆️ Back to Top
num Dec_Round
ExampleDec_Round demonstrates decimal rounding
Code
func ExampleDec_Round() {
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())
}
⬆️ Back to Top
num Dec_Sub
ExampleDec_Sub demonstrates decimal subtraction
Code
func ExampleDec_Sub() {
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())
}
⬆️ Back to Top
num MustDecFromAny
ExampleMustDecFromAny demonstrates creating a decimal from any supported type
Code
func ExampleMustDecFromAny() {
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())
}
⬆️ Back to Top
num MustDecFromString
ExampleMustDecFromString demonstrates creating a decimal from a string (panics on error)
Code
func ExampleMustDecFromString() {
price := MustDecFromString("999.99")
fmt.Printf("Price: %s\n", price.String())
if f, ok := price.Float64(); ok {
fmt.Printf("As float: %.2f\n", f)
}
}
⬆️ Back to Top
num NewDecFromFloat
ExampleNewDecFromFloat demonstrates creating a decimal from a float
Code
func ExampleNewDecFromFloat() {
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())
}
⬆️ Back to Top
num NewDecFromInt
ExampleNewDecFromInt demonstrates creating a decimal from an integer
Code
func ExampleNewDecFromInt() {
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())
}
⬆️ Back to Top
num NewDecFromString
ExampleNewDecFromString demonstrates creating a decimal from a string
Code
func ExampleNewDecFromString() {
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())
_, err = NewDecFromString("invalid")
fmt.Printf("Invalid string error: %v\n", err != nil)
}
⬆️ Back to Top
⬆️ Back to Top
⛓️ 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
slices All
ExampleAll demonstrates checking if all elements satisfy a condition.
Code
func ExampleAll() {
numbers := []int{1, 2, 3, 4, 5}
allPositive := All(numbers, func(n int) bool {
return n > 0
})
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)
}
⬆️ Back to Top
slices Contains
ExampleContains demonstrates checking if any element satisfies a condition.
Code
func ExampleContains() {
numbers := []int{1, 2, 3, 4, 5}
hasLarge := Contains(numbers, func(n int) bool {
return n > 3
})
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)
}
⬆️ Back to Top
slices Filter
ExampleFilter demonstrates filtering a slice to keep only elements that satisfy a condition.
Code
func ExampleFilter() {
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
evenNumbers := Filter(numbers, func(n int) bool {
return n%2 == 0
})
fmt.Println(evenNumbers)
}
⬆️ Back to Top
slices FilterMap
ExampleFilterMap demonstrates filtering and transforming in a single operation.
Code
func ExampleFilterMap() {
numbers := []int{1, 2, 3, 4, 5, 6}
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)
}
⬆️ Back to Top
slices Find
ExampleFind demonstrates finding the first element that matches a condition.
Code
func ExampleFind() {
names := []string{"Alice", "Bob", "Charlie", "David"}
result, found := Find(names, func(name string) bool {
return len(name) > 0 && name[0] == 'C'
})
fmt.Printf("Found: %t, Name: %s\n", found, result)
}
⬆️ Back to Top
slices Fold
ExampleFold demonstrates folding a slice with an initial value.
Code
func ExampleFold() {
words := []string{"Hello", "World", "from", "Go"}
result := Fold(words, func(acc, word string) string {
if acc == "" {
return "Greeting: " + word
}
return acc + " " + word
}, "")
fmt.Printf("Result: %s\n", result)
}
⬆️ Back to Top
slices Map
ExampleMap demonstrates transforming elements in a slice.
Code
func ExampleMap() {
numbers := []int{1, 2, 3, 4, 5}
squares := Map(numbers, func(n int) int {
return n * n
})
fmt.Println(squares)
}
⬆️ Back to Top
slices Reduce
ExampleReduce demonstrates combining all elements into a single value.
Code
func ExampleReduce() {
numbers := []int{1, 2, 3, 4, 5}
sum := Reduce[int, int](numbers, func(acc, curr int) int {
return acc + curr
})
fmt.Println(sum)
}
⬆️ Back to Top
slices Some
ExampleSome demonstrates checking if some elements satisfy a condition.
Code
func ExampleSome() {
words := []string{"hello", "world", "go", "programming"}
hasShort := Some(words, func(word string) bool {
return len(word) < 4
})
fmt.Printf("Has short words: %t\n", hasShort)
}
⬆️ Back to Top
slices ToMap
ExampleToMap demonstrates converting a slice to a map using a key function.
Code
func ExampleToMap() {
words := []string{"apple", "banana", "cherry"}
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'])
}
⬆️ Back to Top
⬆️ Back to Top
🌊 Streams
Package streams provides interfaces and types for reading and writing streams of data.
Functions
streams Batch
ExampleBatch demonstrates grouping stream elements into batches.
Code
func ExampleBatch() {
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
stream := MemReader(data, nil)
batchStream := Batch(stream, 3)
result, _ := Consume(batchStream)
for i, batch := range result {
fmt.Printf("Batch %d: %v\n", i+1, batch)
}
}
⬆️ Back to Top
streams CSV
ExampleCSV demonstrates reading CSV data from a string.
Code
func ExampleCSV() {
csvData := "name,age,city\nAlice,25,NYC\nBob,30,LA\nCharlie,35,Chicago"
reader := io.NopCloser(strings.NewReader(csvData))
csvStream, _ := CSV[[]string](
WithCSVReader(reader),
WithCSVSeparator(","),
)
result, _ := Consume(csvStream)
for i, row := range result {
fmt.Printf("Row %d: %v\n", i+1, row)
}
}
⬆️ Back to Top
streams CSVTransform
ExampleCSVTransform demonstrates converting a stream to CSV format.
Code
func ExampleCSVTransform() {
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 := CSVTransform(stream, CSVSeparatorComma)
transform.WriteTo(os.Stdout)
}
⬆️ Back to Top
streams CSVTransform_tabSeparated
ExampleCSVTransform_tabSeparated demonstrates CSV with tab separator.
Code
func ExampleCSVTransform_tabSeparated() {
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 := CSVTransform(stream, CSVSeparatorTab)
transform.WriteTo(os.Stdout)
}
⬆️ Back to Top
streams ConsumeErrSkip
ExampleConsumeErrSkip demonstrates consuming a stream while skipping errors.
Code
func ExampleConsumeErrSkip() {
reader := strings.NewReader("1\n2\ninvalid\n4\n5")
numbersStream := Lines(reader)
filterStream := FilterMap(numbersStream, func(s string) (int, bool) {
if s == "invalid" {
return 0, false
}
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
}
})
numbers := ConsumeErrSkip(filterStream)
fmt.Printf("Valid numbers: %v\n", numbers)
}
⬆️ Back to Top
streams DB
ExampleDB demonstrates how to use DB with database rows.
Code
func ExampleDB() {
mockData := &mockRows{
data: [][]any{
{1, "Alice"},
{2, "Bob"},
{3, "Charlie"},
},
}
stream := DB(mockData, func(rows DBRows, user *User) error {
return rows.Scan(&user.ID, &user.Name)
})
for stream.Next() {
user := stream.Data()
fmt.Printf("User ID: %d, Name: %s\n", user.ID, user.Name)
}
if err := stream.Err(); err != nil {
log.Printf("Error during streaming: %v", err)
}
}
⬆️ Back to Top
streams Filter
ExampleFilter demonstrates filtering a stream of integers to keep only even numbers.
Code
func ExampleFilter() {
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
stream := MemReader(data, nil)
evenStream := Filter(stream, func(n int) bool {
return n%2 == 0
})
result, _ := Consume(evenStream)
fmt.Println(result)
}
⬆️ Back to Top
streams FilterMap
ExampleFilterMap demonstrates filtering and transforming in a single operation.
Code
func ExampleFilterMap() {
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
stream := MemReader(data, nil)
evenStrings := FilterMap(stream, func(n int) (string, bool) {
if n%2 == 0 {
return strconv.Itoa(n), true
}
return "", false
})
result, _ := Consume(evenStrings)
fmt.Println(result)
}
⬆️ Back to Top
streams Flatten
ExampleFlatten demonstrates flattening a stream of slices.
Code
func ExampleFlatten() {
data := [][]int{{1, 2}, {3, 4, 5}, {6}, {7, 8, 9}}
stream := MemReader(data, nil)
flattened := Flatten(stream)
result, _ := Consume(flattened)
fmt.Println(result)
}
⬆️ Back to Top
streams Group
ExampleGroup demonstrates grouping consecutive items with the same key.
Code
func ExampleGroup() {
data := []string{"apple", "apricot", "banana", "blueberry", "cherry", "coconut"}
stream := MemReader(data, nil)
Grouped := Group(stream, func(s string) rune {
return rune(s[0])
})
result, _ := Consume(Grouped)
for _, group := range result {
fmt.Printf("Group: %v\n", group)
}
}
⬆️ Back to Top
streams JSON
ExampleJSON demonstrates reading JSON data line by line.
Code
func ExampleJSON() {
jsonData := `{"name":"Alice","age":25}
{"name":"Bob","age":30}
{"name":"Charlie","age":35}`
reader := strings.NewReader(jsonData)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
jsonStream := JSON[Person](io.NopCloser(reader))
result, _ := Consume(jsonStream)
for _, person := range result {
fmt.Printf("Person: %s, Age: %d\n", person.Name, person.Age)
}
}
⬆️ Back to Top
streams JSONEachRowTransform
ExampleJSONEachRowTransform demonstrates converting a stream to JSON lines format.
Code
func ExampleJSONEachRowTransform() {
type LogEntry struct {
Timestamp string `json:"timestamp"`
Level string `json:"level"`
Message string `json:"message"`
}
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 := JSONEachRowTransform(stream)
transform.WriteTo(os.Stdout)
}
⬆️ Back to Top
streams JSONTransform
ExampleJSONTransform demonstrates converting a stream to JSON array format.
Code
func ExampleJSONTransform() {
type Person struct {
ID int `json:"id"`
Name string `json:"name"`
}
people := []Person{
{ID: 1, Name: "Alice"},
{ID: 2, Name: "Bob"},
{ID: 3, Name: "Charlie"},
}
stream := MemReader(people, nil)
transform := JSONTransform(stream)
transform.WriteTo(os.Stdout)
}
⬆️ Back to Top
streams Lines
ExampleLines demonstrates reading lines from a string.
Code
func ExampleLines() {
text := "line1\nline2\nline3\n"
reader := strings.NewReader(text)
lineStream := Lines(reader)
result, _ := Consume(lineStream)
fmt.Println(result)
}
⬆️ Back to Top
streams Map
ExampleMap demonstrates transforming elements in a stream.
Code
func ExampleMap() {
data := []int{1, 2, 3, 4, 5}
stream := MemReader(data, nil)
stringStream := Map(stream, func(n int) string {
return fmt.Sprintf("number_%d", n)
})
result, _ := Consume(stringStream)
fmt.Println(result)
}
⬆️ Back to Top
streams MemWriter
ExampleMemWriter demonstrates writing items to memory.
Code
func ExampleMemWriter() {
writer := MemWriter[string]()
items := []string{"hello", "world", "from", "memory"}
for _, item := range items {
writer.Write(item)
}
result := writer.Items()
fmt.Printf("Items written: %d\n", len(result))
fmt.Printf("Items: %v\n", result)
}
⬆️ Back to Top
streams Multicast
ExampleMulticast demonstrates broadcasting a stream to multiple destinations.
Code
func ExampleMulticast() {
reader := strings.NewReader("1\n2\n3\n4\n5")
source := Lines(reader)
dest1 := MemWriter[string]()
dest2 := MemWriter[string]()
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())
}
⬆️ Back to Top
streams Pipe
ExamplePipe demonstrates piping data from one stream to another.
Code
func ExamplePipe() {
data := []string{"hello", "world", "from", "streams"}
source := MemReader(data, nil)
dest := MemWriter[string]()
bytesWritten, _ := Pipe(source, dest)
fmt.Printf("Items written: %d\n", bytesWritten)
fmt.Printf("Items: %v\n", dest.Items())
}
⬆️ Back to Top
streams PipeCSV
ExamplePipeCSV demonstrates using the PipeCSV convenience function.
Code
func ExamplePipeCSV() {
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)
rowsWritten, err := PipeCSV(stream, os.Stdout, CSVSeparatorComma)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Rows written: %d\n", rowsWritten)
}
⬆️ Back to Top
streams PipeJSON
ExamplePipeJSON demonstrates using the PipeJSON convenience function.
Code
func ExamplePipeJSON() {
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price"`
}
products := []Product{
{ID: 1, Name: "Laptop", Price: 999.99},
{ID: 2, Name: "Mouse", Price: 29.99},
}
stream := MemReader(products, nil)
bytesWritten, err := PipeJSON(stream, os.Stdout)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("\nBytes written: %d\n", bytesWritten)
}
⬆️ Back to Top
streams PipeJSONEachRow
ExamplePipeJSONEachRow demonstrates using the PipeJSONEachRow convenience function.
Code
func ExamplePipeJSONEachRow() {
type Metric struct {
Name string `json:"name"`
Value float64 `json:"value"`
Unit string `json:"unit"`
}
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)
bytesWritten, err := PipeJSONEachRow(stream, os.Stdout)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Bytes written: %d\n", bytesWritten)
}
⬆️ Back to Top
streams Reader
ExampleReader demonstrates reading byte chunks from an io.Reader.
Code
func ExampleReader() {
data := "line1\nline2\nline3\n"
reader := strings.NewReader(data)
stream := Reader(reader)
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])
}
⬆️ Back to Top
streams Reduce
ExampleReduce demonstrates using Reduce to sum numbers from a stream.
Code
func ExampleReduce() {
reader := strings.NewReader("10\n20\n30\n40\n50")
lines := Lines(reader)
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)
}
⬆️ Back to Top
streams ReduceMap
ExampleReduceMap demonstrates reducing a stream to a map with aggregated values.
Code
func ExampleReduceMap() {
reader := strings.NewReader("apple\nbanana\napple\ncherry\nbanana\napple")
stream := Lines(reader)
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"])
}
⬆️ Back to Top
streams ReduceSlice
ExampleReduceSlice demonstrates collecting filtered items from a stream.
Code
func ExampleReduceSlice() {
reader := strings.NewReader("cat\ndog\nelephant\nant\nbutterfly\nbird")
stream := Lines(reader)
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)
}
⬆️ Back to Top
streams WriteAll
ExampleWriteAll demonstrates writing a slice to a stream.
Code
func ExampleWriteAll() {
data := []string{"hello", "world", "streams"}
writer := MemWriter[string]()
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())
}
⬆️ Back to Top
⬆️ Back to Top
🔞 Zero
Zero-value utilities and string manipulation functions.
Functions
zero B2S
ExampleB2S demonstrates converting []byte to string without memory allocation
Code
func ExampleB2S() {
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))),
)
}
⬆️ Back to Top
zero S2B
ExampleS2B demonstrates converting a string to []byte without memory allocation
Code
func ExampleS2B() {
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])),
)
}
⬆️ Back to Top
⬆️ Back to Top