| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 | package configimport (	"errors"	"fmt"	"dario.cat/mergo"	"git.ikuban.com/server/yaml"	"github.com/elliotchance/orderedmap/v3"	"github.com/go-kratos/kratos/v2/config")func Load(sources []Source, bc any) error {	configSources := make([]config.Source, 0)	sourceMap := orderedmap.NewOrderedMap[string, any]() // 有序map控制优先级	for _, source := range sources {		if !source.Validate() {			continue		}		s, err := source.NewSource()		if err != nil {			return fmt.Errorf("%v, new source error: %v", source.String(), err)		}		kvs, err := s.Load()		if err != nil {			return fmt.Errorf("%v, source load error: %v", source.String(), err)		}		for _, v := range kvs {			sourceMap.Set(v.Key, map[string]any{})		}		configSources = append(configSources, s)	}	if sourceMap.Len() == 0 {		return errors.New("config source is empty")	}	c := config.New(		config.WithSource(configSources...),		config.WithDecoder(func(kv *config.KeyValue, v map[string]interface{}) error {			ok := sourceMap.Has(kv.Key)			if !ok {				return errors.New("unknown config key")			}			next := map[string]any{}			err := yaml.Unmarshal(kv.Value, next)			if err != nil {				return err			}			sourceMap.Set(kv.Key, convertMap(next))			merged := make(map[string]any)			for c := range sourceMap.Values() {				err = mergo.Merge(&merged, c, mergo.WithOverride)				if err != nil {					return err				}			}			b, err := yaml.Marshal(merged)			if err != nil {				return err			}			err = yaml.Unmarshal(b, bc)			if err != nil {				return err			}			return nil		}),	)	if err := c.Load(); err != nil {		return err	}	return nil}func convertMap(src interface{}) interface{} {	switch m := src.(type) {	case map[string]interface{}:		dst := make(map[string]interface{}, len(m))		for k, v := range m {			dst[k] = convertMap(v)		}		return dst	case map[interface{}]interface{}:		dst := make(map[interface{}]interface{}, len(m))		for k, v := range m {			dst[k] = convertMap(v)		}		return dst	case []interface{}:		dst := make([]interface{}, len(m))		for k, v := range m {			dst[k] = convertMap(v)		}		return dst	case []byte:		// there will be no binary data in the config data		return string(m)	default:		return src	}}
 |