Documentation ¶
Overview ¶
Package config implements configuration related helpers and primitives.
It works with optionally embedded struct types as configuration containers and relies on struct tags for functionality.
Config reads the "config" tag from struct fields. It accepts multiple key/value pairs which must be separated by ";".
Index ¶
- Constants
- Variables
- func CompareInterfaces(a, b interface{}) int
- func CompareValues(a, b reflect.Value) int
- func Default(config interface{}, reset bool) error
- func GetProgramConfigPath() string
- func GetSystemConfigPath() (path string, err error)
- func GetUserConfigPath() (path string, err error)
- func InitializeInterfaces(config interface{}) (bool, error)
- func Limit(config interface{}, clamp bool) error
- func ReadConfigFile(filename string, config interface{}) error
- func RegisterInterfaces(config interface{}) error
- func RegisterType(value interface{}) error
- func RegisteredTypeNames() []string
- func Sanitize(config interface{}) error
- func SanitizeValue(v reflect.Value) error
- func WriteConfigFile(filename string, config interface{}) error
- type Dir
- func (d *Dir) LoadConfig(name string, override bool, out interface{}) (err error)
- func (d *Dir) LoadProgramConfig(name string, out interface{}) error
- func (d *Dir) LoadSystemConfig(name string, out interface{}) error
- func (d *Dir) LoadUserConfig(name string, out interface{}) error
- func (d *Dir) RemoveUser() error
- func (d *Dir) SaveProgramConfig(name string, in interface{}) error
- func (d *Dir) SaveSystemConfig(name string, in interface{}) error
- func (d *Dir) SaveUserConfig(name string, in interface{}) error
- func (d *Dir) System() string
- func (d *Dir) User() string
- type Interface
Examples ¶
Constants ¶
const ( // ConfigTag is the name of the struct field tag read by this package. // It can contain multiple supported key=value pairs separated by ";". ConfigTag = "config" // NilKey is a tag that specifies the value for the field to be interpreted // as nil/empty for non-pointer field value types. NilKey = "nil" // RangeKey is a tag that defines range or set of values for the field. // Sets are sets of values delimited by ",", e.g. 1,2,3 foo,bar. // Ranges are min and max values separated by a ":", e.g. 0:100, 0: :100. // Just the ":" character is legal for a range value, and it inforces no // range. RangeKey = "range" // DefaultKey is a tag that defines the default value for the field. DefaultKey = "default" )
Variables ¶
var ( // ErrConfig is the base error of config package. ErrConfig = errorex.New("config") // ErrInvalidParam is returned when an invalid parameter is passed to a // function. ErrInvalidParam = ErrConfig.Wrap("invalid parameter") // ErrUnsupportedOS is returned by GetSystemConfigPath and // GetUserConfigPath on an unsupported OS. ErrUnsupportedOS = ErrConfig.WrapFormat("unsupported OS '%s'") )
var ( // ErrNoConfigLoaded is returned by LoadConfig when no configs were loaded. ErrNoConfigLoaded = ErrConfig.Wrap("no configuration files loaded") // ErrProgramDir is returned when trying to write or read from // a program directory on an platform that does not support it. // i.e., NOT Windows. ErrProgramDir = ErrConfig.Wrap("program directory configuration not supported on this os") )
var ( // ErrWarning is returned when an error occurs during parsing of one // or more struct tags that carry a config key. ANy fields that produced // errors are stored in the returned error's Extra field. It is up to the // user to consider errors fatal or not. ErrWarning = ErrConfig.Wrap("warning") // ErrParse help. ErrParse = ErrConfig.Wrap("parse '%s'") // ErrNoTag is returned when a field in the config struct does not have a // Config tag defined or the tag has no defined keys. ErrNoTag = ErrConfig.WrapFormat("'%s' no config tag") // ErrInvalidTag is returned when an invalid tag is encountered on a field. ErrInvalidTag = ErrConfig.WrapFormat("'%s' invalid tag") // ErrNoRange help. ErrNoRange = ErrConfig.WrapFormat("'%s' no range defined") // ErrInvalidRange help. ErrInvalidRange = ErrConfig.WrapFormat("'%s' invalid range") // ErrNoDefault is returned when a field in the config struct does not have // a default value defined. ErrNoDefault = ErrConfig.WrapFormat("'%s' no default defined") // ErrInvalidDefault is returned when an invalid value was defined for // default field value. ErrInvalidDefault = ErrConfig.WrapFormat("'%s' invalid default") // ErrInvalidNil help. ErrInvalidNil = ErrConfig.WrapFormat("'%s' invalid default") )
var ( // ErrInvalidType is returned when an Interface.Type value is invalid. ErrInvalidType = ErrConfig.Wrap("invalid type") )
Functions ¶
func CompareInterfaces ¶ added in v0.0.10
func CompareInterfaces(a, b interface{}) int
CompareInterfaces compares two interfaces for equality between the types contained within them. See CompareValues for details.
func CompareValues ¶ added in v0.0.10
CompareValues recursively compares two possibly compound values a and b for equality. It returns:
a negative number (-1) if a is less than b. a zero (0) if a is equal to b. a positive number (1) if a is more than b.
Comparison is done using magic as described below:
Types are compared for reflect.Kind equality first and foremost. Comparison logic is taken as a and b's index in reflect.Kind enumeration.
For structs, only published fields are enumerated and compared. Private fields do not affect comparison. A struct with less public fields returns a less result. Structs with equal number of fields are compared alphabetically ascending comparing field value kinds, names and finally values.
Comparisons between two Arrays and/or slices return a less result for values with less dimensions. In equal dimensioned arrays or slices bytes are compared using bytes.Compare().
Maps with less elements return a less result. Maps with equal number of keys are compared for same kinds, then key names and finally equal values. Comparison is done in ascending order after converting keys to strings/bytes.
Pointer types are dereferenced do their values before comparison. Untyped pointers are compared by their address numerically.
Complex numbers are compared as strings.
Channel and func types are not supported, are ignored and will return 0.
If an error occurs it is returned with a compare value that should be disregarded.
func Default ¶ added in v0.0.7
Default takes a pointer to a config struct and recursively traverses possibly nested fields with config tags then sets their field values to values defined under default key if their values are zero of their type or match the value defined under nil key. e.g. nil for *int, 0 for int, or "" for strings.
If reset is specified all fields with defined defaults are reset, regardless if they have already been initialized to non-nil values or their value has since been changed.
If any errors or warnings occured it returns an ErrParseWarning of type *errorex.ErrorEx that contains all warnings is its' Extras field. It is returned under following conditions:
If a field has no tag defined an ErrNoTag is appended to Extras. If a field has no default value an ErrNoDefault is appended to Extras. If a field has an incompatible/invalid default value defined an ErrInvalidDefault is appended to Extras.
Any other errors signify a no-op and a failure.
Example ¶
type Example struct { Name string `config:"default=foo"` PName *string `config:"default=foo"` PPName **string `config:"default=foo"` Age int `config:"default=42"` PAge *int `config:"default=42"` Ping int `config:"nil=10;default=30"` Pong int `config:"nil=10;default=30"` } p := &Example{Ping: 10, Pong: 20} if err := Default(p, false); err != nil { fmt.Println(err) } fmt.Printf("Name:%s PName:%s, PPName:%s, Age:%d PAge:%d Ping:%d Pong:%d\n", p.Name, *p.PName, **p.PPName, p.Age, *p.PAge, p.Ping, p.Pong)
Output: Name:foo PName:foo, PPName:foo, Age:42 PAge:42 Ping:30 Pong:20
func GetProgramConfigPath ¶
func GetProgramConfigPath() string
GetProgramConfigPath returns path to the directory of the executable.
func GetSystemConfigPath ¶
GetSystemConfigPath returns the path to the base system configuration directory that depends on the running OS and is defined as follows:
darwin: "/private/etc" unix, linux et al: "/etc" windows: "%ALLUSERSPROFILE%"
If an unsupported OS is detected returns empty path and ErrUnsupportedOS.
func GetUserConfigPath ¶
GetUserConfigPath returns the path to the base user configuration directory that depends on the running OS and is defined as follows:
darwin: "$HOME" unix, linux et al: "$HOME" windows: "%USERPROFILE%"
If an unsupported OS is detected returns empty path and ErrUnsupportedOS.
func InitializeInterfaces ¶
InitializeInterfaces takes a pointer to a possibly compound struct and preallocates Interface.Value fields at any depth with values of type registered under Interface.Type so that the data is unmarshaled into a proper type instead of a generic interface map.
Config is modified by this function, possibly even in case of an error. InitializeInterfaces exclusively modifies contained Interface types.
If config is not a pointer to a struct an ErrInvalidParam is returned. If an Interface with an unregistered Interface.Type value is found ErrInvalidType is returned that possibly wraps the cause of the error.
On success returns a boolean specifying if one or more Interfaces were initialized and a nil error.
func Limit ¶ added in v0.0.7
Limit takes a pointer to a config struct and recursively traverses possibly nested fields with config tags then if clamp was specified and their values are outside of defined range or set, sets their field values to values within the set or range, otherwise it just generates a warning. e.g. range=1;2;3 range=foo;bar range=0:100
If clamp is specified fields with values outside of defined ranges are set to lowest or highest value defined, depending on boundary they exceed. If the value is not within the set a default operation is applied to the field.
Limit supports enforcing sets and ranges and precognizes them as follows: Choices are strings separated by a ",", e.g.: 1,2,3 foo,bar,baz Ranges are two values separated by a ":", e.g.: 0: :100 0:100 or : Both range boundaries are optional, although that defeats the purpose. Supported kinds are String, Ints, Uints.
If any errors or warnings occured it returns an ErrParseWarning of type *errorex.ErrorEx that contains all warnings is its' Extras field. It is returned under following conditions:
If a field has no tag defined an ErrNoTag is appended to Extras. If a field has no range value an ErrNoRange is appended to Extras. If a field has an incompatible/invalid range value defined an ErrInvalidRange is appended to Extras.
Any other errors signify a no-op and a failure.
Example ¶
type Example struct { Name string `config:"range=foo,bar,baz;default=foobar"` Age int `config:"range=7:77;default=42"` } p := &Example{} if err := Limit(p, true); err != nil { fmt.Println(err) } fmt.Printf("Name:%s Age:%d\n", p.Name, p.Age)
Output: Name:foobar Age:7
func ReadConfigFile ¶
ReadConfigFile reads a configuration file specified by filename into config which must be a non-nil pointer to a value compatible with configuration being read.
Codec is selected from extension and must be registered by importing it in the program or package.
ReadConfigFile unmarshals the loaded stream twice if any Interface structs are detected at any level in config whose Type field is not empty. First run reads Interface.Type fields and initializes Interface.Value to zero values of that type then unmarshals the config again to fill ethe Value fields.
Types must be registered with the registry in order for Interfaces to be initialized properly. Types are registered automatically when using WriteConfigFile and can be manually registered using RegisterType.
If an error occurs it is returned.
func RegisterInterfaces ¶
func RegisterInterfaces(config interface{}) error
RegisterInterfaces takes a pointer to a possibly compound struct and registers types of values in Interface.Value fields at any depth with config registry then writes their names into Interface.Type fields.
Config is modified by this function, possibly even in case of an error. RegisterInterfaces exclusively modifies contained Interface types.
Interface values with an empty Value field are skipped silently. Interface values with a non-empty Type field are skipped silently.
If config is not a pointer to a struct an ErrInvalidParam is returned.
func RegisterType ¶
func RegisterType(value interface{}) error
RegisterType registers a type of specified value with the config registry.
func RegisteredTypeNames ¶ added in v0.0.6
func RegisteredTypeNames() []string
RegisteredTypeNames returns a slice of registered type names with config.
func Sanitize ¶
func Sanitize(config interface{}) error
Sanitize takes a pointer to a config struct and recursively traverses possibly nested fields with config tags then applies the Default and Limit operations on those fields. For details see Default and Limit.
Nested config structs are searched for in arrays, slices, maps of struct fields. Only non-compound typed fields and pointers to such fields can be defaulted, i.e. strings, bools, ints, pointers to such types and fields whose type implements a TextUnmarshaler.
Returns ErrWarning of type (*errorex.ErrorEx) if any warnings occured with list of warnings retrievable via its' Extras method.
Any other errors signify a no-op and a failure.
func SanitizeValue ¶ added in v0.0.7
SanitizeValue is like Sanitize but takes a reflect value of config.
func WriteConfigFile ¶
WriteConfigFile writes config to a file specified by filename. Codec is selected from filename extension and must be registered. WriteConfigFile registers all Interface types in config at any depth. If an error occurs it is returned.
Types ¶
type Dir ¶
type Dir struct {
// contains filtered or unexported fields
}
Dir is a helper that represents a configuration directory in multiple locations defined by priorities, namely: System, User and Local/Executable level.
A Dir takes a prefix which defines a subdirectory in either of configuration locations. If prefix is a path it is rooted at either configuration location being accessed.
func NewDir ¶
NewDir returns a new Dir with the given prefix or an error.
Prefix represents the name of the directory to be read/written in any of locations Dir recognizes. It can be a directory name or a path in case of which it will be rooted at all configuration locations.
func (*Dir) LoadConfig ¶
LoadConfig searches for and loads configuration file specified by name in the following locations:
program directory (windows only) user configuration directory system configuration directory
File is read into out which must be a non-nil pointer to a variable compatible with config file being loaded.
If override is not specified first found file in the order decribed above is loaded.
If override is specified all found config files from all locations are loaded in reverse order described above with config files loaded later overriding any values loaded to out thus far.
If a config file with the specified name is not found in any locations an ErrNoConfigLoaded is returned.
name specifies the name of the configuration file including extension which selects the codec to use when reading the file and must be registered.
An optional path in the specified name is rooted at the configuration directory being read and specifies a path to a file in a subdirectory of the configuration directory.
func (*Dir) LoadProgramConfig ¶
LoadProgramConfig loads the config specified by name from the program directory. See LoadConfig for details.
Loading configuration from program directory is supported on windows only.
If an error occurs it is returned.
func (*Dir) LoadSystemConfig ¶
LoadSystemConfig loads the config specified by name from the system config directory. See LoadConfig for details.
If an error occurs it is returned.
func (*Dir) LoadUserConfig ¶
LoadUserConfig loads the config specified by name from the user config directory. See LoadConfig for details.
If an error occurs it is returned.
func (*Dir) RemoveUser ¶ added in v0.0.7
RemoveUser removes Dir's configuration directory from user configuration location.
func (*Dir) SaveProgramConfig ¶
SaveProgramConfig saves a configuration file defined by name to the executable directory.
Prefix is ignored when saving to program directory but if name contains a path it is respected and subdirectories are created inside the program directory.
Saving to program directory is only supported on Windows.
If an error occurs it is returned.
func (*Dir) SaveSystemConfig ¶
SaveSystemConfig saves a configuration file defined by name to the system configuration subdirectory defined by Dir prefix. If name contains a path Subdirectories are created if they don't exist.
Executable must have permission to write to system locations.
If an error occurs it is returned.
func (*Dir) SaveUserConfig ¶
SaveUserConfig saves a configuration file defined by name to the user configuration subdirectory defined by Dir prefix. If name contains a path Subdirectories are created if they don't exist.
If an error occurs it is returned.
type Interface ¶
type Interface struct { // Type holds the name of the type contained in Value. // It should not be modified by user. // It is populated when marshaling the Value and read when unmarshaling it. Type string // Value is the value being wrapped. Value interface{} }
Interface is a wrapper for marshalling interface values to and from abstract data formats such as JSON that do not store type information by design.
It uses a type registry to allocate values of correct type into an interface prior to unmarshaling data into it to avoid unmarshaling to generic map[string]interface{} type for JSON, or similar for other packages. User still needs to assert the correct Value type when accessing it.
Interfaces use a single config package-wide type registry that generates custom names for types contained in Value.
Directories ¶
Path | Synopsis |
---|---|
Package codec defines a config codec interface.
|
Package codec defines a config codec interface. |
gob
Package gob implements a GOB Config Codec.
|
Package gob implements a GOB Config Codec. |
json
Package json implements a JSON COnfog Codec.
|
Package json implements a JSON COnfog Codec. |
xml
Package xml is the XML Config Codec.
|
Package xml is the XML Config Codec. |