conf

package
v1.2.2 Latest Latest
Warning

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

Go to latest
Published: Aug 10, 2025 License: Apache-2.0 Imports: 18 Imported by: 0

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:

  1. Expression validation using expr tag: type Config struct { Port int `expr:"$ > 0 && $ < 65535"` }

  2. 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

Constants

This section is empty.

Variables

View Source
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

func RegisterConverter[T any](fn Converter[T])

RegisterConverter registers its converter for non-primitive type such as time.Time, time.Duration, or other user-defined value type.

func RegisterReader

func RegisterReader(r Reader, ext ...string)

RegisterReader registers its Reader for some kind of file extension.

func RegisterSplitter

func RegisterSplitter(name string, fn Splitter)

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.

func (*BindParam) BindTag

func (param *BindParam) BindTag(tag string, validate reflect.StructTag) error

BindTag parses and binds the configuration tag to the BindParam. It handles default values and nested key expansion.

type Converter

type Converter[T any] func(string) (T, error)

Converter converts a string to a target type T.

type Filter added in v1.1.2

type Filter interface {
	Do(i any, param BindParam) (bool, error)
}

Filter defines an interface for filtering configuration fields during binding.

type MutableProperties added in v1.2.0

type MutableProperties struct {
	*storage.Storage
}

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 Map

func Map(m map[string]any) *MutableProperties

Map creates *MutableProperties from map.

func New

func New() *MutableProperties

New creates empty *MutableProperties.

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.

func (*MutableProperties) Resolve added in v1.2.0

func (p *MutableProperties) Resolve(s string) (string, error)

Resolve resolves string value that contains references to other properties, the references are defined by ${key:=def}.

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.

func ParseTag

func ParseTag(tag string) (ret ParsedTag, err error)

ParseTag parses a tag string in the format `${key:=default}>>splitter` into a ParsedTag struct. Returns an error if the format is invalid.

func (ParsedTag) String added in v1.2.0

func (tag ParsedTag) String() string

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 Reader

type Reader func(b []byte) (map[string]any, error)

Reader parses []byte into nested map[string]any.

type Splitter

type Splitter func(string) ([]string, error)

Splitter splits string into []string by some characters.

type ValidateFunc added in v1.2.0

type ValidateFunc[T any] func(T) bool

ValidateFunc defines a type for validation functions, which accept a value of type T and return a boolean result.

Directories

Path Synopsis
reader
Package storage provides hierarchical configuration storage and path parsing utilities.
Package storage provides hierarchical configuration storage and path parsing utilities.

Jump to

Keyboard shortcuts

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