Documentation
¶
Index ¶
- func Assert(opts ...AssertOpt) error
- func EnvFileLookup(filePath string) func(string) (string, bool)
- func IgnoreEmptyEnvLookup(key string) (string, bool)
- func Read[T any](holder *T, lookupEnv ...func(string) (string, bool)) error
- type AssertOpt
- func Custom(condition bool, field, message string) AssertOpt
- func FileExists(path, field string) AssertOpt
- func MaxLength(value string, max int, field string) AssertOpt
- func MaxSliceLen(length, max int, field string) AssertOpt
- func MinLength(value string, min int, field string) AssertOpt
- func MinSliceLen(length, min int, field string) AssertOpt
- func NonNegative[T Number](value T, field string) AssertOpt
- func Not(opt AssertOpt, customMessage string) AssertOpt
- func NotBlank(value, field string) AssertOpt
- func NotEmpty(value, field string) AssertOpt
- func NotEquals[T comparable](value, forbidden T, field string) AssertOpt
- func OneOf(value string, field string, allowed ...string) AssertOpt
- func Pattern(value, field, pattern string) AssertOpt
- func Positive[T Number](value T, field string) AssertOpt
- func Range[T Number](value, min, max T, field string) AssertOpt
- func URL(value, field string) AssertOpt
- type ErrValidation
- type Number
- type Validator
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Assert ¶ added in v0.2.0
Assert runs all provided validation checks and collects any errors that occur. If any validation fails, it returns an ErrValidation containing all failures. If all validations pass, it returns nil.
Assert is designed to be used with validation helper functions like NotEmpty, Range, etc. All validations are executed regardless of failures, allowing users to see all validation issues at once rather than fixing them one at a time.
Example:
func (cfg Config) Validate() error {
return Assert(
NotEmpty(cfg.APIKey, "API_KEY"),
Range(cfg.Port, 1, 65535, "PORT"),
OneOf(cfg.Environment, "ENVIRONMENT", "dev", "staging", "production"),
)
}
func EnvFileLookup ¶
EnvFileLookup returns a lookup function that reads environment variables from a .env file. It panics if a file cannot be read. The .env file should have lines in the format KEY=VALUE. Comments starting with # are ignored. Empty lines are ignored. Notes:
- If both the .env file and OS environment define a key, the OS environment value wins (current behavior).
- Lines like `export KEY=VALUE` are supported.
func IgnoreEmptyEnvLookup ¶
IgnoreEmptyEnvLookup wraps os.LookupEnv but treats empty values as unset. If the variable is present but "", it returns ok == false.
func Read ¶
Read populates holder (a pointer to struct) using the provided lookup function to resolve values.
Usage:
type C struct {
Port int `env:"PORT" envDefault:"8080"`
TLS struct {
Enabled bool `env:"ENABLED"`
Cert string `env:"CERT" envRequired:"true"`
} `envPrefix:"TLS"` // effective keys: TLS_ENABLED, TLS_CERT
}
var cfg C
if err := envconfig.Read(&cfg); err != nil { log.Fatal(err) }
Lookup source:
By default Read uses os.LookupEnv. You may pass a custom lookup function, e.g., envconfig.Read(&cfg, myLookup) where myLookup has signature func(string) (string, bool).
Tags (per field):
- `env:"NAME"` : the environment variable name for this field. Use `env:"-"` to skip the field entirely.
- `envDefault:"VAL"` : fallback used only when the variable is UNSET (i.e., lookup returns ok == false). If the variable is present but empty ("", ok == true), the empty value is used and default does NOT apply.
- `envRequired:"true"`: if the variable is UNSET and no envDefault is provided, Read returns an error. Only the literal "true" enables this behavior.
- `envPrefix:"PFX"` : for struct-typed fields (including embedded/ anonymous ones). Applies a prefix to all descendant leaf env names. Prefixes are joined with "_". Example: `envPrefix:"DB"` -> DB_HOST, DB_PORT.
Embedded vs named struct fields:
- Embedded (anonymous) struct fields are treated "flat" by default (no extra prefix). To prefix an embedded subtree, put `envPrefix` on the embedded field.
- Named struct fields may also carry `envPrefix:"PFX"`; they must NOT also have an `env` tag.
Whole-struct (single-key) decoding:
If a struct-typed field (or embedded struct) has an effective prefix PFX_, and the holder type implements one of the standard decoders below, a single env variable named "PFX" (without the trailing underscore) can be used to populate the entire struct at once. When present, this whole-struct value takes precedence and field-by-field decoding is skipped. Supported decoders: - encoding.TextUnmarshaler - encoding.BinaryUnmarshaler - json.Unmarshaler
Supported field types:
- primitives: string, bool, all int/uint sizes, float32/64
- time.Duration (parsed via time.ParseDuration)
- arrays, slices: comma-separated values (e.g. "a,b,c")
- maps: comma-separated k=v pairs (e.g. "k1=v1,k2=v2"); split on first "="
- pointers to any supported type (allocated as needed)
- any type implementing encoding.TextUnmarshaler / BinaryUnmarshaler / json.Unmarshaler
Precedence per leaf field:
- If lookupEnv returns (value, ok==true), that value is used as-is (even if value is the empty string "").
- Else, if `envDefault` is present, it is used.
- Else, if `envRequired:"true"`, Read returns an error.
- Else, the field is left at its zero value.
Validation & errors:
- holder must be a non-nil pointer to a struct.
- Non-embedded struct fields must have either `env` or `envPrefix` (or be explicitly skipped with `env:"-"`); otherwise an error is returned.
- Struct fields must not specify both `env` and `envPrefix`.
- `envPrefix` must not be empty when present.
- Parsing/conversion failures return errors that include the env key.
- Unsupported leaf types (that do not implement a supported unmarshal interface) cause an error.
- any type can implement Validator interface, and it will be called as soon as value if populated.
Note on empties:
An env var that is present but empty (lookup ok == true, value == "") is considered "set": it suppresses `envDefault` and does not trigger `envRequired`. If you want defaulting on empty strings, use IgnoreEmptyEnvLookup, which wraps os.LookupEnv and treats empty values as unset (returns ok == false when value == "").
Types ¶
type AssertOpt ¶ added in v0.2.0
type AssertOpt func() error
AssertOpt represents a single validation check that returns an error if validation fails. AssertOpt functions are designed to be composable and can be passed to Assert() to perform multiple validations at once.
Example:
func (cfg MyConfig) Validate() error {
return Assert(
NotEmpty(cfg.Host, "HOST"),
Range(cfg.Port, 1, 65535, "PORT"),
)
}
func Custom ¶ added in v0.2.0
Custom validates a custom condition and returns a specified error message if it fails. This is a generic validator for arbitrary conditions that don't fit other helpers. Returns an AssertOpt that fails if the condition is false.
Parameters:
- condition: the boolean condition to check
- field: the name of the field (used in error messages)
- message: the error message to return if the condition is false
Example:
Custom(cfg.MaxRetries < cfg.Timeout, "TIMEOUT", "must be greater than MAX_RETRIES")
func FileExists ¶ added in v0.2.0
FileExists validates that a file or directory exists at the specified path. Returns an AssertOpt that fails if the path does not exist.
Parameters:
- path: the file or directory path to check
- field: the name of the field (used in error messages)
Example:
FileExists(cfg.ConfigFile, "CONFIG_FILE")
func MaxLength ¶ added in v0.2.0
MaxLength validates that a string does not exceed the specified maximum length. Returns an AssertOpt that fails if the string length is greater than max.
Parameters:
- value: the string to validate
- max: the maximum allowed length
- field: the name of the field (used in error messages)
Example:
MaxLength(cfg.Username, 50, "USERNAME")
func MaxSliceLen ¶ added in v0.2.0
MaxSliceLen validates that a slice does not exceed the specified maximum length. Returns an AssertOpt that fails if the slice length is greater than max.
Parameters:
- length: the actual length of the slice
- max: the maximum allowed length
- field: the name of the field (used in error messages)
Example:
MaxSliceLen(len(cfg.Tags), 10, "TAGS")
func MinLength ¶ added in v0.2.0
MinLength validates that a string has at least the specified minimum length. Returns an AssertOpt that fails if the string length is less than min.
Parameters:
- value: the string to validate
- min: the minimum required length
- field: the name of the field (used in error messages)
Example:
MinLength(cfg.Password, 8, "PASSWORD")
func MinSliceLen ¶ added in v0.2.0
MinSliceLen validates that a slice has at least the specified minimum length. Returns an AssertOpt that fails if the slice length is less than min.
Parameters:
- length: the actual length of the slice
- min: the minimum required length
- field: the name of the field (used in error messages)
Example:
MinSliceLen(len(cfg.Servers), 1, "SERVERS")
func NonNegative ¶ added in v0.2.0
NonNegative validates that an integer value is greater than or equal to zero. Returns an AssertOpt that fails if the value is negative.
Parameters:
- value: the integer to validate
- field: the name of the field (used in error messages)
Example:
NonNegative(cfg.Retries, "RETRIES")
func Not ¶ added in v0.2.0
Not inverts any AssertOpt, making it fail when the original would succeed and succeed when the original would fail. This is useful for creating negative assertions from existing validators. Returns an AssertOpt that inverts the result of the provided validator.
Parameters:
- opt: the AssertOpt to invert
- customMessage: optional custom error message (if empty, a generic message is used)
Example:
Not(OneOf(cfg.Environment, "ENV", "production", "staging"), "must not be production or staging") Not(Pattern(cfg.Username, "USERNAME", `^admin.*`), "username must not start with 'admin'")
func NotBlank ¶ added in v0.2.0
NotBlank validates that a string is not empty and not just whitespace. NotEmpty is already defined, but here's NotBlank for completeness Returns an AssertOpt that fails if the value is empty or contains only whitespace.
Parameters:
- value: the string to validate
- field: the name of the field (used in error messages)
Example:
NotBlank(cfg.APIKey, "API_KEY")
func NotEmpty ¶ added in v0.2.0
NotEmpty validates that a string value is not empty. Returns an AssertOpt that fails if the value is an empty string.
Parameters:
- value: the string to validate
- field: the name of the field (used in error messages)
Example:
NotEmpty(cfg.APIKey, "API_KEY")
func NotEquals ¶ added in v0.2.0
func NotEquals[T comparable](value, forbidden T, field string) AssertOpt
NotEquals validates that a value does not equal the forbidden value. This is a generic function that works with any comparable type. Returns an AssertOpt that fails if the value equals the forbidden value.
Parameters:
- value: the value to validate
- forbidden: the value that should not be matched
- field: the name of the field (used in error messages)
Example:
NotEquals(cfg.Port, 22, "PORT") // disallow SSH port NotEquals(cfg.Mode, "insecure", "MODE") NotEquals(cfg.AdminPassword, "admin", "ADMIN_PASSWORD")
func OneOf ¶ added in v0.2.0
OneOf validates that a string value matches one of the allowed values. The comparison is case-sensitive. Returns an AssertOpt that fails if the value is not in the allowed list.
Parameters:
- value: the string to validate
- field: the name of the field (used in error messages)
- allowed: the list of allowed values
Example:
OneOf(cfg.LogLevel, "LOG_LEVEL", "debug", "info", "warn", "error")
func Pattern ¶ added in v0.2.0
Pattern validates that a string matches the specified regular expression pattern. Returns an AssertOpt that fails if the string does not match the pattern or if the pattern itself is invalid.
Parameters:
- value: the string to validate
- field: the name of the field (used in error messages)
- pattern: the regular expression pattern to match against
Example:
Pattern(cfg.Email, "EMAIL", `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
func Positive ¶ added in v0.2.0
Positive validates that an integer value is greater than zero. Returns an AssertOpt that fails if the value is less than or equal to zero.
Parameters:
- value: the integer to validate
- field: the name of the field (used in error messages)
Example:
Positive(cfg.Workers, "WORKERS")
func Range ¶ added in v0.2.0
Range validates that an integer value falls within a specified range (inclusive). Returns an AssertOpt that fails if the value is less than min or greater than max.
Parameters:
- value: the integer to validate
- min: the minimum allowed value (inclusive)
- max: the maximum allowed value (inclusive)
- field: the name of the field (used in error messages)
Example:
Range(cfg.Port, 1, 65535, "PORT")
func URL ¶ added in v0.2.0
URL validates that a string is a valid URL according to Go's url.Parse. Returns an AssertOpt that fails if the URL cannot be parsed.
Parameters:
- value: the URL string to validate
- field: the name of the field (used in error messages)
Example:
URL(cfg.APIEndpoint, "API_ENDPOINT")
type ErrValidation ¶ added in v0.2.0
type ErrValidation []error
ErrValidation is a collection of validation errors that occurred during Assert(). It implements the error interface and formats multiple errors into a single, human-readable error message.
func (ErrValidation) Error ¶ added in v0.2.0
func (e ErrValidation) Error() string
Error returns a formatted string containing all validation errors, separated by semicolons.