pocket

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 13, 2026 License: MIT Imports: 16 Imported by: 0

README

Pocket

Pocket provides utility functions for common patterns that aren't in the Go standard library but I find useful in almost every project.

No external dependencies, just the standard library.

You can add it as a dependency to your project or you can just copy the parts that you find useful.

Installation

go get github.com/germanDV/pocket

Directory Functions

HomeDir

Returns the home directory of the current user.

home, _ := pocket.HomeDir()
fmt.Println("Home:", home)
ConfigDir

Returns the configuration directory.

configDir, _ := pocket.ConfigDir()
fmt.Println("Config:", configDir)
DataDir

Returns the data directory.

dataDir, _ := pocket.DataDir()
fmt.Println("Data:", dataDir)

Slice Functions

Map

Applies a function to each element of a slice and returns a new slice with the results.

numbers := []int{1, 2, 3}
doubled := pocket.Map(numbers, func(n int) int {
    return n * 2
})
// doubled = [2, 4, 6]
Filter

Returns a new slice containing only elements for which the predicate function returns true.

numbers := []int{1, 2, 3, 4, 5}
even := pocket.Filter(numbers, func(n int) bool {
    return n%2 == 0
})
// even = [2, 4]

Safe Math Functions

SafeAdd

Returns the sum of two integers, panicking if the result overflows or underflows.

sum := pocket.SafeAdd(100, 200)            // 300
sum = pocket.SafeAdd(uint8(255), uint8(1)) // panics: unsigned integer overflow
SafeSub

Returns the difference of two integers, panicking if the result overflows or underflows.

diff := pocket.SafeSub(100, 50)           // 50
diff = pocket.SafeSub(uint8(0), uint8(1)) // panics: unsigned integer underflow

Test Assertion Functions

  • AssertNotNil Asserts that the given value is not nil.
  • AssertNil Asserts that the given value is nil.
  • AssertTrue Asserts that the given value is true.
  • AssertFalse Asserts that the given value is false.
  • AssertEqual Asserts that two values are deeply equal.
  • AssertNotEqual Asserts that two values are not deeply equal.
  • AssertErrorIs Asserts that an error is of the expected type using errors.Is.
  • AssertContains Asserts that a string contains a substring.
  • AssertPanics Asserts that the given function panics.

Configuration Functions

LoadConfigFromEnv

Populates a config struct from environment variables. Uses env and default struct tags.

type AppConfig struct {
    Port     int           `env:"PORT" default:"8080"`
    LogLevel string        `env:"LOG_LEVEL"`
    Timeout  time.Duration `env:"TIMEOUT" default:"10s"`
}

config, err := pocket.LoadConfigFromEnv[AppConfig]()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Port: %d\n", config.Port)

Supported types: string, int, bool, time.Duration

String Functions

SafeCompare

Performs a constant-time comparison of two strings to protect against timing attacks. It hashes both strings using SHA-256 to ensure they have the same length before comparison.

result := pocket.SafeCompare("secret_token", "secret_token") // true
result = pocket.SafeCompare("token1", "token2")              // false
GenerateString

Generates a random string of the specified length using crypto/rand. The result is base64 URL-encoded. Note: The returned string will be longer than the input length due to base64 encoding. Panics if random number generation fails.

token := pocket.GenerateString(32) // Random URL-safe string

Money Functions

Pocket provides a Money type for working with monetary values. Money instances are immutable and support safe arithmetic operations with overflow protection.

NewUSD

Creates a new Money instance with USD currency (precision 2).

m := pocket.NewUSD(100_99)
fmt.Println(m.Format())   // "100.99 USD"
NewARS

Creates a new Money instance with ARS currency (precision 2).

m := pocket.NewARS(50_00)
fmt.Println(m.Format())  // "50.00 ARS"
NewMoney

Creates a new Money instance with custom currency and precision.

m, err := pocket.NewMoney(100_99, "EUR", 2)
if err != nil {
    log.Fatal(err)
}
fmt.Println(m.String()) // "100.99"
NewMoneyFromString

Creates a new Money instance from a string in the format "amount currency". The number of decimal places determines the precision. So be sure to include 0s if necessary. And be careful not to use unsanitized user input as "100 USD" will be different from "100.00 USD".

m, err := pocket.NewMoneyFromString("100.99 USD")
if err != nil {
    log.Fatal(err)
}
fmt.Println(m.Amount()) // 10099

// Works with any precision
btc, _ := pocket.NewMoneyFromString("1.00000000 BTC")
fmt.Println(btc.Precision()) // 8

// Currency is case-insensitive
m2, _ := pocket.NewMoneyFromString("50.00 usd")
fmt.Println(m2.Currency()) // "USD"
Money.Currency

Returns the currency code of the money.

m := pocket.NewUSD(100)
fmt.Println(m.Currency()) // "USD"
Money.Precision

Returns the precision (number of decimal places) of the money.

m := pocket.NewUSD(100)
fmt.Println(m.Precision()) // 2
Money.Amount

Returns the amount in the smallest unit of the currency (e.g., cents for USD).

m := pocket.NewUSD(100_99)
fmt.Println(m.Amount()) // 10099 (represents $100.99)
Money.String

Returns the amount as a formatted string with proper decimal places.

m := pocket.NewUSD(100_99)
fmt.Println(m.String()) // "100.99"
Money.Format

Returns the amount and currency in "amount currency" format.

m := pocket.NewUSD(100_99)
fmt.Println(m.Format()) // "100.99 USD"
Money.Plus

Returns a new Money with the sum of two amounts. Returns an error if currencies don't match or if overflow occurs.

m1 := pocket.NewUSD(100_00)
m2 := pocket.NewUSD(50_00)
result, err := m1.Plus(m2)
// result = 15000 ($150.00)
Money.Minus

Returns a new Money with the difference of two amounts. Returns an error if currencies don't match or if overflow occurs.

m1 := pocket.NewUSD(100_00)
m2 := pocket.NewUSD(30_00)
result, err := m1.Minus(m2)
// result = 7000 ($70.00)
Money.Inc

Adds a raw amount to the money and returns a new Money instance.

m := pocket.NewUSD(100_00)
result, err := m.Inc(50_00)
// result = 15000 ($150.00)
Money.Dec

Subtracts a raw amount from the money and returns a new Money instance.

m := pocket.NewUSD(100_00)
result, err := m.Dec(30_00)
// result = 7000 ($70.00)
Money.Times

Multiplies the money by a factor and returns a new Money instance.

m := pocket.NewUSD(10_00)
result, err := m.Times(3)
// result = 3000 ($30.00)
Money.DividedBy

Divides the money by a divisor and returns a new Money instance. Uses half-up rounding.

m := pocket.NewUSD(100_00)
result, err := m.DividedBy(3)
// result = 3333 ($33.33)
Money.Equals

Returns true if two Money instances have the same amount, currency, and precision.

m1 := pocket.NewUSD(100_00)
m2 := pocket.NewUSD(100_00)
fmt.Println(m1.Equals(m2)) // true

Documentation

Overview

Package pocket provides utility functions for common patterns that aren't in the Go standard library but are useful to have in your pocket.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AssertContains

func AssertContains(t *testing.T, got string, substr string)

AssertContains asserts that the given string contains the given substring.

func AssertEqual

func AssertEqual[T any](t *testing.T, a T, b T)

AssertEqual asserts that the given values are equal. It uses reflection to do a deep comparison.

func AssertErrorIs

func AssertErrorIs(t *testing.T, got error, want error)

AssertErrorIs asserts that the given error is of the given type. It uses the errors.Is to do the comparison, checking for wrapped errors.

func AssertFalse

func AssertFalse(t *testing.T, got bool)

AssertFalse asserts that the given value is false.

func AssertNil

func AssertNil(t *testing.T, got any)

AssertNil asserts that the given value is nil.

func AssertNotEqual

func AssertNotEqual[T any](t *testing.T, a T, b T)

AssertNotEqual asserts that the given values are not equal. It uses reflection to do a deep comparison.

func AssertNotNil

func AssertNotNil(t *testing.T, got any)

AssertNotNil asserts that the given value is not nil.

func AssertPanics

func AssertPanics(t *testing.T, f func())

AssertPanics asserts that the given function panics.

func AssertTrue

func AssertTrue(t *testing.T, got bool)

AssertTrue asserts that the given value is true.

func ConfigDir

func ConfigDir() (string, error)

ConfigDir returns the configuration directory of the current user. On Unix, it looks for XDG_CONFIG_HOME, defaults to $HOME/.config. On Windows, it checks APPDATA.

func DataDir

func DataDir() (string, error)

DataDir returns the data directory of the current user. On Unix, it looks for XDG_DATA_HOME, defaults to $HOME/.local/share. On Windows, it checks LOCALAPPDATA.

func Filter

func Filter[T any](slice []T, f func(T) bool) []T

Filter applies the given function to each element of the slice and returns a new slice with the elements for which the function returns true.

func GenerateString

func GenerateString(len int) string

GenerateString generates a random string of the specified length. If for any reason `rand.Read` fails, this function will panic!

func HomeDir

func HomeDir() (string, error)

HomeDir returns the home directory of the current user. On Unix, it looks for HOME, defaults to the current user's home directory. On Windows, it checks USERPROFILE first, then HOME, then HOMEDRIVE+HOMEPATH.

func LoadConfigFromEnv

func LoadConfigFromEnv[T any]() (*T, error)

LoadConfigFromEnv returns a config struct populated with environment variables.

It uses the `env` struct tag to determine the environment variable name and the `default` tag to determine the default value if the environment variable is not set. It casts the value to the type specified in the struct field.

Example:

	  type AppConfig struct {
		Port     int           `env:"PORT" default:"8080"`
	    LogLevel string        `env:"LOG_LEVEL"`
       Timeout  time.Duration `env:"TIMEOUT" default:"10s"`
	  }

	  config, err := pocket.LoadConfigFromEnv[AppConfig]()

func Map

func Map[T any, U any](slice []T, f func(T) U) []U

Map applies the given function to each element of the slice and returns a new slice with the results.

func SafeAdd

func SafeAdd[T Int](a T, b T) T

SafeAdd returns the sum of two integers, panicking if the result overflows.

func SafeCompare

func SafeCompare(token1, token2 string) bool

SafeCompare performs a constant-time comparison of two strings to protect against timing attacks. It hashes both strings to ensure they have the same length.

func SafeDiv

func SafeDiv[T Int](a T, b T) T

SafeDiv return the division of two integers, panicking if the result overflows.

func SafeMul

func SafeMul[T Int](a T, b T) T

SafeMul returns the product of two integers, panicking if the result overflows.

func SafeSub

func SafeSub[T Int](a T, b T) T

SafeSub returns the difference of two integers, panicking if the result overflows.

func TrySafeAdd

func TrySafeAdd[T Int](a T, b T) (T, error)

TrySafeAdd returns the sum of two integers. Returns an error if the result would overflow or underflow.

func TrySafeDiv

func TrySafeDiv[T Int](a T, b T) (T, error)

TrySafeDiv returns the division of two integers. Returns an error if the result would overflow or if dividing by zero.

func TrySafeMul

func TrySafeMul[T Int](a T, b T) (T, error)

TrySafeMul returns the product of two integers. Returns an error if the result would overflow.

func TrySafeSub

func TrySafeSub[T Int](a T, b T) (T, error)

TrySafeSub returns the difference of two integers. Returns an error if the result would overflow or underflow.

Types

type Int

type Int interface {
	Signed | Unsigned
}

Int is a type constraint that matches all integer types (signed and unsigned).

type Money

type Money struct {
	// contains filtered or unexported fields
}

Money represents a monetary value. A Money instance is immutable, operations return a new Money instance. Precision is limited to 8 digits to accommdate fairly large values without overflowing.

func NewARS

func NewARS(amount int64) Money

NewARS creates a new Money instance with ARS currency.

func NewMoney

func NewMoney(amount int64, currency string, precision int) (Money, error)

NewMoney creates a new Money instance.

func NewMoneyFromString

func NewMoneyFromString(s string) (Money, error)

NewMoneyFromString creates a new Money instance from a string. The string must be in the format "amount currency". The number of decimal places determines the precision. So be sure to include 0s if necessary. And be careful not to use unsanitized user input as "100 USD" will be different from "100.00 USD". e.g., "100.99 USD" // precision=2 e.g., "100.00 ARS" // precision=2 e.g., "100 ARS" // precision=0, not what you want for ARS (and most FIAT currencies) e.g., "1.00000000 BTC" // precision=8

func NewUSD

func NewUSD(amount int64) Money

NewUSD creates a new Money instance with USD currency.

func (Money) Amount

func (m Money) Amount() int64

Returns the amount of money in the smallest unit of the currency. For example, if money is `Money{amount: 10099, currency: "USD"}`, the amount will be 10099.

func (Money) Currency

func (m Money) Currency() string

Returns the currency of the money.

func (Money) Dec

func (m Money) Dec(amount int64) (Money, error)

Dec subtracts the given amount from the money.

func (Money) DividedBy

func (m Money) DividedBy(divisor int64) (Money, error)

DividedBy returns a new Money instance with the amount divided by the given divisor. Uses half-up rounding: fractions >= 0.5 round up, < 0.5 round down.

func (Money) Equals

func (m Money) Equals(other Money) bool

Equals returns true if the two moneys have the same amount, currency, and precision.

func (Money) Format

func (m Money) Format() string

Format returns "amount currency" format. e.g., "100.99 USD"

func (Money) Inc

func (m Money) Inc(amount int64) (Money, error)

Inc adds the given amount to the money.

func (Money) Minus

func (m Money) Minus(other Money) (Money, error)

Minus returns a new Money with the difference of the two amounts. Returns an error if the currencies don't match or if overflow occurs.

func (Money) Plus

func (m Money) Plus(other Money) (Money, error)

Plus returns a new Money with the sum of the two amounts. Returns an error if the currencies don't match or if overflow occurs.

func (Money) Precision

func (m Money) Precision() int

Returns the precision of the money.

func (Money) String

func (m Money) String() string

String returns the amount in major units with proper decimal places. e.g., amount=10099, precision=2 → "100.99" e.g., amount=1000, precision=2 → "10.00" e.g., amount=-10099, precision=2 → "-100.99"

func (Money) Times

func (m Money) Times(amount int64) (Money, error)

Times returns a new Money with the product of the two amounts.

type Signed

type Signed interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64
}

Signed is a type constraint that matches all signed integer types.

type Unsigned

type Unsigned interface {
	~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}

Unsigned is a type constraint that matches all unsigned integer types.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL