Documentation
¶
Overview ¶
Package conf provides a configuration binding framework with hierarchical resolution, type-safe mapping, and validation capabilities.
Core Concepts: ¶
The framework enables mapping configuration data from multiple sources into Go structures with:
- Hierarchical property resolution using ${key} syntax - Type-safe binding with automatic conversions - Expression-based validation - Extensible architecture via pluggable components
Tag Syntax: ¶
Struct tags use the following format:
value:"${key:=default}>>splitter"
Key features: - Nested keys (e.g., service.endpoint) - Dynamic defaults (e.g., ${DB_HOST:=localhost:${DB_PORT:=3306}}) - Splitter chaining (e.g., >>json for JSON parsing)
Data Binding: ¶
Supports binding to various types with automatic conversion:
1. Primitives: Uses strconv for basic type conversions 2. Complex Types:
- Slices: From indexed properties or custom splitters
- Maps: Via subkey expansion
- Structs: Recursive binding of nested structures
3. Custom Types: Register converters using RegisterConverter
Validation System: ¶
Expression validation using expr tag: type Config struct { Port int `expr:"$ > 0 && $ < 65535"` }
Custom validators: RegisterValidateFunc("futureDate", func(t time.Time) bool { return t.After(time.Now()) })
File Support: ¶
Built-in readers handle: - JSON (.json) - Properties (.properties) - YAML (.yaml/.yml) - TOML (.toml/.tml)
Register custom readers with RegisterReader.
Property Resolution: ¶
- Recursive ${} substitution - Type-aware defaults - Chained defaults (${A:=${B:=C}})
Extension Points: ¶
1. RegisterSplitter: Add custom string splitters 2. RegisterConverter: Add type converters 3. RegisterReader: Support new file formats 4. RegisterValidateFunc: Add custom validators
Examples: ¶
Basic binding:
type ServerConfig struct { Host string `value:"${host:=localhost}"` Port int `value:"${port:=8080}"` }
Nested structure:
type AppConfig struct { DB Database `value:"${db}"` Timeout string `value:"${timeout:=5s}"` }
Slice binding:
type Config struct { Endpoints []string `value:"${endpoints}"` // Indexed properties Features []string `value:"${features}>>split"` // Custom splitter }
Validation:
type UserConfig struct { Age int `value:"${age}" expr:"$ >= 18"` Email string `value:"${email}" expr:"contains($, '@')"` Expires time.Time `value:"${expires}" expr:"futureDate($)"` }
Index ¶
- Variables
- func BindValue(p Properties, v reflect.Value, t reflect.Type, param BindParam, filter Filter) (RetErr error)
- func RegisterConverter[T any](fn Converter[T])
- func RegisterReader(r Reader, ext ...string)
- func RegisterSplitter(name string, fn Splitter)
- func RegisterValidateFunc[T any](name string, fn ValidateFunc[T])
- type BindParam
- type Converter
- type Filter
- type MutableProperties
- func (p *MutableProperties) Bind(i any, tag ...string) error
- func (p *MutableProperties) CopyTo(out *MutableProperties) error
- func (p *MutableProperties) Data() map[string]string
- func (p *MutableProperties) Get(key string, def ...string) string
- func (p *MutableProperties) Keys() []string
- func (p *MutableProperties) Resolve(s string) (string, error)
- type ParsedTag
- type Properties
- type Reader
- type Splitter
- type ValidateFunc
Constants ¶
This section is empty.
Variables ¶
var ( ErrNotExist = errors.New("not exist") ErrInvalidSyntax = errors.New("invalid syntax") )
Functions ¶
func BindValue ¶
func BindValue(p Properties, v reflect.Value, t reflect.Type, param BindParam, filter Filter) (RetErr error)
BindValue binds a value from properties `p` to the reflect.Value `v` of type `t` using metadata in `param`. It supports primitives, structs, maps, and slices.
func RegisterConverter ¶
RegisterConverter registers its converter for non-primitive type such as time.Time, time.Duration, or other user-defined value type.
func RegisterReader ¶
RegisterReader registers its Reader for some kind of file extension.
func RegisterSplitter ¶
RegisterSplitter registers a Splitter and named it.
func RegisterValidateFunc ¶ added in v1.2.0
func RegisterValidateFunc[T any](name string, fn ValidateFunc[T])
RegisterValidateFunc registers a validation function with a specific name. The function can then be used in validation expressions.
Types ¶
type BindParam ¶
type BindParam struct { Key string // full key Path string // full path Tag ParsedTag // parsed tag Validate reflect.StructTag // full field tag }
BindParam holds binding metadata for a single configuration value.
type Filter ¶ added in v1.1.2
Filter defines an interface for filtering configuration fields during binding.
type MutableProperties ¶ added in v1.2.0
MutableProperties stores the data with map[string]string and the keys are case-sensitive, you can get one of them by its key, or bind some of them to a value. There are too many formats of configuration files, and too many conflicts between them. Each format of configuration file provides its special characteristics, but usually they are not all necessary, and complementary. For example, `conf` disabled Java properties' expansion when reading file, but also provides similar function when getting or binding properties. A good rule of thumb is that treating application configuration as a tree, but not all formats of configuration files designed as a tree or not ideal, for instance Java properties isn't strictly verified. Although configuration can store as a tree, but it costs more CPU time when getting properties because it reads property node by node. So `conf` uses a tree to strictly verify and a flat map to store.
func Load ¶
func Load(file string) (*MutableProperties, error)
Load creates *MutableProperties from file.
func (*MutableProperties) Bind ¶ added in v1.2.0
func (p *MutableProperties) Bind(i any, tag ...string) error
Bind binds properties to a value, the bind value can be primitive type, map, slice, struct. When binding to struct, the tag 'value' indicates which properties should be bind. The 'value' tag are defined by value:"${a:=b}>>splitter", 'a' is the key, 'b' is the default value, 'splitter' is the Splitter's name when you want split string value into []string value.
func (*MutableProperties) CopyTo ¶ added in v1.2.0
func (p *MutableProperties) CopyTo(out *MutableProperties) error
CopyTo copies properties into another by override.
func (*MutableProperties) Data ¶ added in v1.2.0
func (p *MutableProperties) Data() map[string]string
Data returns key-value pairs of the properties.
func (*MutableProperties) Get ¶ added in v1.2.0
func (p *MutableProperties) Get(key string, def ...string) string
Get returns key's value, using Def to return a default value.
func (*MutableProperties) Keys ¶ added in v1.2.0
func (p *MutableProperties) Keys() []string
Keys returns keys of the properties.
type ParsedTag ¶
type ParsedTag struct { Key string // short property key Def string // default value HasDef bool // has default value Splitter string // splitter's name }
ParsedTag represents a parsed configuration tag, including key, default value, and optional custom splitter for list parsing.
type Properties ¶
type Properties interface { // Data returns key-value pairs of the properties. Data() map[string]string // Keys returns keys of the properties. Keys() []string // SubKeys returns the sorted sub keys of the key. SubKeys(key string) ([]string, error) // Has returns whether the key exists. Has(key string) bool // Get returns key's value. Get(key string, def ...string) string // Resolve resolves string that contains references. Resolve(s string) (string, error) // Bind binds properties into a value. Bind(i any, tag ...string) error // CopyTo copies properties into another by override. CopyTo(out *MutableProperties) error }
Properties is the interface for read-only properties.
type ValidateFunc ¶ added in v1.2.0
ValidateFunc defines a type for validation functions, which accept a value of type T and return a boolean result.