go kratos源码及配置解析

 更新时间:2022年12月05日 11:57:55   作者:小宇渣渣渣  
这篇文章主要为大家介绍了go kratos源码及配置解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

相关类图

项目启动时一般前置条件为解析配置文件, 我们看下这块是怎么设计的.

流程解释

  • config 实现 config Interface 接口, 初始化reader对象
  • 调用Load方法, 通过入口注入的不同文件源, 调用实现了source interface 对应的Load方法(以file举例子)
  • file 通过 Load 入口, 判断是目录还是文件, 执行对应的方法, 拿到文件内容返回
  • config 拿到file返回的内容, 交给reader去合并
  • reader 根据文件格式(yml) 转为 map[string]interface{} 结构, 并进行覆盖合并, 将结果存到对象变量上
  • reader 处理完成后, config调用 file watcher 进行文件变更监听, 启动协程监听

由此可见, config对象其实作为入口, 将数据生产交给file、env, 将数据加工解析交给 reader

代码案例

init 接收外部参数定义解析配置文件地址

func init() {
	flag.StringVar(&commonconf, "common", "./configs/local", "common config path, eg: -conf config.yaml")
	flag.StringVar(&flagconf, "conf", "./configs/local/api", "config path, eg: -conf config.yaml")
    flag.Parse()
}

使用config.New初始化文件配置

//初始化配置
//新增两个配置源, 文件格式 common and flagconf 路径
c := config.New(
    config.WithSource(
        file.NewSource(commonconf),
        file.NewSource(flagconf),
    ),
)
// 关闭watch相关的监听器
defer c.Close()
// 加载配置文件
if err := c.Load(); err != nil {
	panic(err)
}
//解析配置到bc结构上
var bc conf.Bootstrap
if err := c.Scan(&bc); err != nil {
    panic(err)
}

我们看下config.New的实现

// 初始化解析器, 关联reader对象, 数据交给由reader加工和存储
func New(opts ...Option) Config {
	o := options{
		decoder:  defaultDecoder,
		resolver: defaultResolver,
	}
	for _, opt := range opts {
		opt(&o)
	}
	return &config{
		opts:   o,
		reader: newReader(o),
	}
}

Options 有下面几个属性

type options struct {
	sources  []Source // 配置源, 由初始化负责传入的source配置源
	decoder  Decoder //  解析器
	resolver Resolver // 变量解析替换
}

执行 Load 配置加载

func (c *config) Load() error {
    // 因为我们在入口传入的是file对象, 所以执行src load的时候也是file对象的 load 方法
	for _, src := range c.opts.sources {
        // 获取文件内容(可能是一个目录, 会存在多个文件)
		kvs, err := src.Load()
		if err != nil {
			return err
		}
		for _, v := range kvs {
			log.Debugf("config loaded: %s format: %s", v.Key, v.Format)
		}
        // 合并配置key
		if err = c.reader.Merge(kvs...); err != nil {
			log.Errorf("failed to merge config source: %v", err)
			return err
		}
        // 调用file watch, 监听文件变化
		w, err := src.Watch()
		if err != nil {
			log.Errorf("failed to watch config source: %v", err)
			return err
		}
		c.watchers = append(c.watchers, w)
        // 异步监听文件变化(调用对应的watch对象)
		go c.watch(w)
	}
    // 解析内容中是否包含 ${APPID:default} 变量
    // 如果在配置文件中存在 APPID: xx 配置, 则进行替换
    // 否则使用default默认值
	if err := c.reader.Resolve(); err != nil {
		log.Errorf("failed to resolve config source: %v", err)
		return err
	}
	return nil
}

异步watch

func (c *config) watch(w Watcher) {
	for {
		kvs, err := w.Next()
		if err != nil {
			if errors.Is(err, context.Canceled) {
				log.Infof("watcher's ctx cancel : %v", err)
				return
			}
			time.Sleep(time.Second)
			log.Errorf("failed to watch next config: %v", err)
			continue
		}
    	// 处理逻辑忽略 .....
		c.cached.Range(func(key, value interface{}) bool {
			k := key.(string)
			v := value.(Value)
			if n, ok := c.reader.Value(k); ok && reflect.TypeOf(n.Load()) == reflect.TypeOf(v.Load()) && !reflect.DeepEqual(n.Load(), v.Load()) {
				v.Store(n.Load())
				if o, ok := c.observers.Load(k); ok {
					o.(Observer)(k, v)
				}
			}
			return true
		})
	}
}

Scan 将配置转换成结构体

var bc conf.Bootstrap
if err := c.Scan(&bc); err != nil {
    panic(err)
}

以上就是go kratos源码及配置解析的详细内容,更多关于kratos源码配置的资料请关注脚本之家其它相关文章!

相关文章

  • Go语言深度拷贝工具deepcopy的使用教程

    Go语言深度拷贝工具deepcopy的使用教程

    今天给大家推荐的工具是deepcopy,一个可以对指针、接口、切片、结构体、Map都能进行深拷贝的工具,感兴趣的小伙伴快跟随小编一起学习学习
    2022-09-09
  • GO中使用谷歌GEMINI模型任务代码实例

    GO中使用谷歌GEMINI模型任务代码实例

    这篇文章主要为大家介绍了GO中使用谷歌GEMINI模型任务代码实例探究,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • 从基础到高阶解析Go语言中数组的应用

    从基础到高阶解析Go语言中数组的应用

    在本文中,我们将从基础概念、常规操作,到高级技巧和特殊操作,带大家深入了解Go语言中数组的各个方面,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-10-10
  • Golang并发编程深入分析

    Golang并发编程深入分析

    golang中的并发,是函数相互独立运行的能力,goroutines是并发运行的函数。golang提供了goroutines作为并发处理的一种方式
    2022-11-11
  • 夯实Golang基础之数据类型梳理汇总

    夯实Golang基础之数据类型梳理汇总

    这篇文章主要8为大家介绍了夯实Golang基础之数据类型梳理汇总,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2023-10-10
  • Golang中函数(Function)和方法(Method)的区别详解

    Golang中函数(Function)和方法(Method)的区别详解

    在Golang中,大家必然会频繁使用到函数(Function)和方法(Method),但是有的同学可能并没有注意过函数和方法的异同点,函数和方法都是用来执行特定任务的代码块,虽然很相似,但也有很大的区别,所以本文将详细讲解函数和方法的定义以及它们的异同点
    2023-07-07
  • Go递归修改文件名的实例代码

    Go递归修改文件名的实例代码

    这篇文章主要介绍了Go递归修改文件名的实例代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的饿参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • Golang使用Channel组建高并发HTTP服务器

    Golang使用Channel组建高并发HTTP服务器

    Golang 作为一门高效的语言,在网络编程方面表现也非常出色,这篇文章主要介绍了如何使用 Golang 和 Channel 组建高并发 HTTP 服务器,感兴趣的可以了解一下
    2023-06-06
  • 基于Go和PHP语言实现爬楼梯算法的思路详解

    基于Go和PHP语言实现爬楼梯算法的思路详解

    这篇文章主要介绍了Go和PHP 实现爬楼梯算法,本文通过动态规划和斐波那契数列两种解决思路给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • Go单元测试对数据库CRUD进行Mock测试

    Go单元测试对数据库CRUD进行Mock测试

    这篇文章主要为大家介绍了Go单元测试对数据库CRUD进行Mock测试的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06

最新评论