Documentation ¶
Overview ¶
Package config is a light yet powerful config loader.
Load ¶
Configuration loading is as easy as:
if err := config.Load(&cfg, config.WithSources( sourcefile.New("./config.yaml"), sourceenv.New("myapp"), )); err != nil { panic(err) }
See each sources to get more details on how to use them.
Defaults ¶
Set default recursively by walking through any types and try to apply defaults.
A default is applied if the type implement the setDefaultFunc interface and the actual value is the zero value of the type.
Applying defaults ¶
Considering the following structure:
type Furniture struct{ Color Color Weight float64 IsAvailable bool } func (f *Furniture) SetDefault() { f.IsAvailable = true } type ( Color string ) const ( ColorUnknown = Color("unknown") ColorBlack = Color("black") ColorGreen = Color("green") ) func (c *Color) SetDefault() { *c = ColorUnknown }
If we want to apply defaults to an instance of furniture, we just have to:
var f Furniture defaulter.SetDefault(&f) // f has an unknown color and is available
Special cases when using defaults ¶
We already see that the SetDefault method will be call if any value is the zero value and value's type implements SetDefault. There is two exception:
If the type is a pointer:
type Furniture struct{ IsAvailable bool OwnerAddress *Address } type Address string func (a *Address) SetDefault() { *a = "nowhere" } func foo() { var f Funiture defaulter.SetDefault(&f) // even if Address type implements SetDefault, the method will not be call // as f.OwnerAddress is nil, and we may want to keep it that way }
If it's a struct field with the `default:"-"` tag:
type Furniture struct{ IsAvailable bool OwnerAddress Address `default:"-"` } func (a *Address) SetDefault() { *a = "nowhere" } func (f *Furniture) SetDefault() { f.IsAvailable = true } funf foo() { var f Furniture defaulter.SetDefault(&f) // here f.IsAvailable is true // but f.OwnderAddress still contains the zero value, because of the `nodefault` tag }
Validation ¶
Configuration validation can be made to validate types implementing validateFunc. It recursively walk through any types and call validateFunc if defined, for any of them.
Considering the following structure:
type Furniture struct{ Color Color Weight float64 IsAvailable bool } func (f Furniture) Validate() error { if !f.IsAvailable { return fmt.Errorf("furniture is not available") } return nil } type ( Color string ) const ( ColorUnknown = Color("unknown") ColorBlack = Color("black") ColorGreen = Color("green") ) func (c Color) Validate() error { if *c == ColorUnknown { return fmt.Errorf("unknown color") } return nil }
If we want to validate to an instance of furniture, we just have to:
f := getFurniture() validator.Validate(f) // which will fail if furniture is not available or has an unknown color
Index ¶
- func InitializeNewValueOfTypeWithJSON(typ reflect.Type, jsonData []byte) (*reflect.Value, error)
- func InitializeNewValueOfTypeWithString(typ reflect.Type, str string) (*reflect.Value, error)
- func Load(cfg interface{}, opts ...Option) error
- func SetDefault(i interface{}) error
- func SetNewValue(oldValue, newValue *reflect.Value) (bool, error)
- func Validate(i interface{}) error
- type Config
- type Option
- type Source
- type SourceCreationFunc
- type SourceSetValueFromConfigTreePath
- type SourceUnmarshal
- type ValidationError
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func InitializeNewValueOfTypeWithJSON ¶
InitializeNewValueOfTypeWithJSON . nolint: gocyclo
func InitializeNewValueOfTypeWithString ¶
InitializeNewValueOfTypeWithString .
func Load ¶
Load creates a new instance (see New), and call the Load method of it (see Config.Load).
Example ¶
package main import ( "fmt" "os" "github.com/krostar/config" sourceenv "github.com/krostar/config/source/env" ) type Config struct { NoDefault string Some OtherConfig SomeOther *OtherConfig SomeLast *OtherConfig } type OtherConfig struct { UniversalAnswer int } func (c *OtherConfig) SetDefault() { c.UniversalAnswer = 42 } func main() { var cfg Config os.Setenv("MYAPP_SOMEOTHER_UNIVERSALANSWER", "1010") // nolint: errcheck, gosec defer os.Unsetenv("MYAPP_SOMEOTHER_UNIVERSALANSWER") // nolint: errcheck, gosec if err := config.Load(&cfg, config.WithSources( sourceenv.New("myapp"), )); err != nil { panic(err) } fmt.Printf("cfg.NoDefault = %q\n", cfg.NoDefault) fmt.Printf("cfg.Some.UniversalAnswer = %d\n", cfg.Some.UniversalAnswer) fmt.Printf("cfg.SomeOther.UniversalAnswer = %d\n", cfg.SomeOther.UniversalAnswer) fmt.Printf("cfg.SomeLast = %v\n", cfg.SomeLast) }
Output: cfg.NoDefault = "" cfg.Some.UniversalAnswer = 42 cfg.SomeOther.UniversalAnswer = 1010 cfg.SomeLast = <nil>
func SetDefault ¶
func SetDefault(i interface{}) error
SetDefault tries to set default to the provided interface. For a default to be applied, the interface needs to implement the `setDefaultFunc` interface, or to contain any fields (in case of a struct) that implement it. The SetDefault method will be called only if the value is the zero value.
Example ¶
package main import ( "fmt" "github.com/krostar/config" ) type HTTPConfig struct { Debug bool ListenAddress string } func (c *HTTPConfig) SetDefault() { c.ListenAddress = "127.0.0.1:8080" } func (c HTTPConfig) Validate() error { if c.ListenAddress == "" { return fmt.Errorf("listening address can't be empty") } return nil } func main() { var cfg HTTPConfig if err := config.SetDefault(&cfg); err != nil { panic("unable to set defaults") } fmt.Println("debug:", cfg.Debug) fmt.Println("listen-address:", cfg.ListenAddress) }
Output: debug: false listen-address: 127.0.0.1:8080
func Validate ¶
func Validate(i interface{}) error
Validate calls validateFunc for all types that implements it.
Example ¶
package main import ( "fmt" "github.com/krostar/config" ) type HTTPConfig struct { Debug bool ListenAddress string } func (c *HTTPConfig) SetDefault() { c.ListenAddress = "127.0.0.1:8080" } func (c HTTPConfig) Validate() error { if c.ListenAddress == "" { return fmt.Errorf("listening address can't be empty") } return nil } func main() { cfg := HTTPConfig{ Debug: false, ListenAddress: "", } err := config.Validate(&cfg) fmt.Println("failed:", err != nil) fmt.Println("reason:", err.Error()) }
Output: failed: true reason: validation error: listening address can't be empty
Types ¶
type Config ¶
type Config struct {
// contains filtered or unexported fields
}
Config stores the source configuration applied through options.
type Option ¶
Option defines the function signature to apply options.
func WithRawSources ¶
WithRawSources appends the given initializd source to the list of configuration sources.
func WithSources ¶
func WithSources(sf ...SourceCreationFunc) Option
WithSources appends the given source to the list of configuration sources.
type Source ¶
type Source interface {
Name() string
}
Source defines the interface any source must implements.
type SourceCreationFunc ¶
SourceCreationFunc defines how to creates a new source.
type SourceSetValueFromConfigTreePath ¶
type SourceSetValueFromConfigTreePath interface { Source SetValueFromConfigTreePath(v *reflect.Value, treePath string) (bool, error) }
SourceSetValueFromConfigTreePath defines a way to set explicitly each values from each configuration paths.
type SourceUnmarshal ¶
SourceUnmarshal defines a way to apply a source to a config via unmarshalling directly to it.
type ValidationError ¶
ValidationError contains all validation errors. Keys are field in error (with arboresence) and value the error. Key can be empty if the root interface failed.
func (ValidationError) String ¶
func (v ValidationError) String() string
String implements Stringer for ValidationError.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
internal
|
|
trivialerr
Package trivialerr helps to define and use trivial (not critical) errors.
|
Package trivialerr helps to define and use trivial (not critical) errors. |
source
|
|
env
Package sourceenv sources configuration from env.
|
Package sourceenv sources configuration from env. |
file
Package sourcefile sources configuration from file.
|
Package sourcefile sources configuration from file. |