package internal import ( "errors" "github.com/go-kratos/kratos/v2/log" "sync" // init encoding _ "github.com/go-kratos/kratos/v2/encoding/json" _ "github.com/go-kratos/kratos/v2/encoding/proto" _ "github.com/go-kratos/kratos/v2/encoding/xml" _ "github.com/go-kratos/kratos/v2/encoding/yaml" ) var ( // ErrNotFound is key not found. ErrNotFound = errors.New("key not found") // ErrTypeAssert is type assert error. ErrTypeAssert = errors.New("type assert error") _ Config = (*config)(nil) ) // Observer is config observer. type Observer func(string, Value) // Config is a config interface. type Config interface { Load() error Bytes() ([]byte, error) Value(key string) Value } type config struct { opts options reader Reader cached sync.Map observers sync.Map log *log.Helper } // New new a config with options. func New(opts ...Option) Config { o := options{ logger: log.DefaultLogger, decoder: defaultDecoder, resolver: defaultResolver, } for _, opt := range opts { opt(&o) } return &config{ opts: o, reader: newReader(o), log: log.NewHelper(o.logger), } } func (c *config) Load() error { for _, src := range c.opts.sources { kvs, err := src.Load() if err != nil { return err } if err = c.reader.Merge(kvs...); err != nil { c.log.Errorf("failed to merge config source: %v", err) return err } } if err := c.reader.Resolve(); err != nil { c.log.Errorf("failed to resolve config source: %v", err) return err } return nil } func (c *config) Bytes() ([]byte, error) { return c.reader.Bytes() } func (c *config) Value(key string) Value { if v, ok := c.cached.Load(key); ok { return v.(Value) } if v, ok := c.reader.Value(key); ok { c.cached.Store(key, v) return v } return &errValue{err: ErrNotFound} }