最近在用go重构,在先前的代码中,我们使用的ini文件进行配置,但是因为很多历史遗留问题,导致配置混乱,维护困难,自然也需要考虑重构了。

通用配置格式

通用的配置格式有很多,常用的就有ini,json,yaml,xml等,当然为了通用我们不考虑自定义的配置格式。那如何选择呢?

首先,xml我们就不用考虑了,到现在为止我都没觉得用这玩意配置起来有多方便,反而很臃肿,可能java系的童鞋会比较青睐。

再来考虑ini,ini文件对于简单应用的配置可以说是非常方便的,如果配置没有太多的层次结构,使用ini就能完全满足我们的需要,即使有,我们也能够通过加入特定前缀来解决。譬如,我们可能有如下redis配置:

[ModuleA]

persistent_redis_addr = 127.0.0.1:6379
persistent_redis_password = admin cache_redis_addr = 127.0.0.1:6380
cache_redis_password = admin

然后,需求变化了,我们需要另一个持久化redis服务来做相关事情,于是配置就可能变成了下面这样:

[ModuleA]

persistent_redis_addr = 127.0.0.1:6379
persistent_redis_password = admin persistent2_redis_addr = 127.0.0.1:6379
persistent2_redis_password = admin cache_redis_addr = 127.0.0.1:6380
cache_redis_password = admin

虽然通过前缀命名能解决层级问题,但总觉得是对程序员不怎么友好的。

why json

剩下的就是json和yaml,可以这么说,这两个都算是比较好的轻量级配置格式,而且对程序员非常友好,而且go里面都可以通过定义struct,将层级结构的配置映射到相应的struct里面。

但是我还是决定选择json作为我们go代码的默认配置格式,最主要的原因在于go的json包有一个杀手级别的RawMessage实现。而这个在我能找到的yaml包中没有。

RawMessage主要是用来告诉go延迟解析用的。当我们定义了某一个字段为RawMessage之后,go就不会解析这段json,这样我们就可以将其推后到各自的子模块单独解析。

假设有一个功能,后台存储可能是redis或者mysql,但是只会使用一个,可能我们会按照如下方式写配置:

redis_store : {
addr : 127.0.0.1
db : 0
}, mysql_store : {
addr : 127.0.0.1
db : test
password : admin
user : root
} store : redis

对应的class为

type Config struct {
RedisStore struct {
Addr string
DB int
} MysqlStore Struct {
Addr string
DB string
Password string
User string
} Store string
}

如果这时候我们在增加了一种新的store,我们需要在Config文件里面在增加一个新的field,但是实际我们只会使用一种store,并不需要写这么多的配置。

我们可以使用RawMessage来处理:

type Config struct {
Store string
StoreConfig json.RawMessage
}

如果使用redis,对应的配置文件为

store: redis
store_config: {
addr : 127.0.0.1
db : 0
}

如果使用mysql,对应的配置文件为

store: mysql
store_config: {
addr : 127.0.0.1
db : test
password : admin
user : root
}

go读取配置文件之后,并不会处理RawMessage对应的东西,而是由我们代码自己对应的store模块去处理。这样无论配置文件怎么变动,store模块做了什么变动,都不会影响Config类。

而在各个模块中,我们只需要自己定义相关config,然后可以将RawMessage直接解析映射到该config上面,譬如,对于redis,我们在模块中有如下定义

type RedisConfig config {
Addr string `json:"addr"`
DB int `json:"db"`
} func NewConfig(m json.RawMessage) *RedisConfig {
c := new(RedisConfig) json.Unmarshal(m, c) return c
}

json的不足

使用json也还有很多蛋疼的地方,最大的问题就在于注释,在json中,可不能这样写:

{
//this is a comment
/*this is a comment*/
}

但是,我们又不可能不写一点注释来说明配置项是干啥的,所以,通常采用的是引入一个comment字段的方式,譬如:

{
"_comment" : "this is a comment",
"key" : "value"
}

另外,json还需要注意的就是写的时候最后一项不能加上逗号,这样的json会因为格式错误无法解析的。

{
"key" : "value",
}

最后那个逗号可是不能要的,但是实际写配置的时候我们可是经常性的随手加上了。

但是,总的来说,json对于go的项目还是很友好的,我不光在项目中推行了,在自己的开源项目中,也大量的采用了json作为主要的配置文件。

在go中使用json作为主要的配置格式的更多相关文章

  1. jquery 解析数据库中的json日期为正常的格式

    //在action从后台数据库中请求获得日期以后,得到的是json格式的数据,因此要解析才能显示在前台1.在jsp页面写的代码如下:<html> <script> Date.p ...

  2. C#中Newtonsoft.Json 序列化和反序列化 时间格式

    步骤 引用 using Newtonsoft.Json; using Newtonsoft.Json.Converters; 格式配置 IsoDateTimeConverter timeFormat ...

  3. 如何正确的使用json?如何在.Net中使用json?

    什么是json json是一种轻量级的数据交换格式,由N组键值对组成的字符串,完全独立于语言的文本格式. 为什么要使用json 在很久很久以前,调用第三方API时,我们通常是采用xml进行数据交互,但 ...

  4. C#中的Json的序列化和反序列化

    Json是一种通用的数据格式,我们在数据交换的时候,经常会用到,下面介绍c#中的json序列化和反序列化,当然也可用在asp.net,silverlight,wpf中.我们在下面实例讲解如何进行Jso ...

  5. SpringMVC中使用Json传数据

    在web项目中使用Json进行数据的传输是非常常见且有用的,在这里介绍下在SpringMVC中使用Json传数据的一种方法,在我的使用中,主要包括下面四个部分(我个人喜好使用maven这类型工具进行项 ...

  6. PHP中生成json信息的方法

    <?php //php中生成json信息 //json_encode(数组/对象) $color = array('red','blue','green'); //[索引数组] echo jso ...

  7. 【ASP.NET Web API教程】6.2 ASP.NET Web API中的JSON和XML序列化

    谨以此文感谢关注此系列文章的园友!前段时间本以为此系列文章已没多少人关注,而不打算继续下去了.因为文章贴出来之后,看的人似乎不多,也很少有人对这些文章发表评论,而且几乎无人给予“推荐”.但前几天有人询 ...

  8. Asp.Net Web API 2第十三课——ASP.NET Web API中的JSON和XML序列化

    前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET W ...

  9. JMeter中返回Json数据的处理方法

    Json 作为一种数据交换格式在网络开发,特别是 Ajax 与 Restful 架构中应用的越来越广泛.而 Apache 的 JMeter 也是较受欢迎的压力测试工具之一,但是它本身没有提供对于 Js ...

随机推荐

  1. jenkins + pipeline构建自动化部署

    一.引言 Jenkins 2.x的精髓是Pipeline as Code,那为什么要用Pipeline呢?jenkins1.0也能实现自动化构建,但Pipeline能够将以前project中的配置信息 ...

  2. redis的数据持久化方案

    Redis的持久化方案有两种 1.Rdb方式:快照形式,定期将内存中的数据持久化到硬盘.是Redis默认的数据持久化的形式. Rdb:缺点是:数据还没有更新到磁盘上,突然断电,造成数据的不完整性. 在 ...

  3. CRM客户关系管理系统(五)

    第五章.分页功能开发 5.1.修改BaseKingAdmin和完善前段页面显示 现在访问没有注册的model会报错,因为基类中没有写list_display和list_filter. 在基类中设置一个 ...

  4. Vue结合slot插槽分发父组件内容实现高度复用、更加灵活的dialog组件

    之前写过一篇关于vue实现dialog会话框组件的文章(http://www.cnblogs.com/fozero/p/8546883.html)[http://www.cnblogs.com/foz ...

  5. Docker环境 ELK 快速部署

    Docker环境 ELK快速部署 环境 Centos 7.4 , Docker version 17.12 Docker至少3GB内存: #内核配置 echo ' vm.max_map_count = ...

  6. gradle 入门介绍

    gradle 简介 基于Groovy实现的自动化构建工具,比maven好的一点在于不用写复杂的xml文件.使用script就可以. gradle 专业名词 从一个build.gradle 文件开始,b ...

  7. Android艺术开发探索——第二章:IPC机制(下)

    Android艺术开发探索--第二章:IPC机制(下) 我们继续来讲IPC机制,在本篇中你将会学习到 ContentProvider Socket Binder连接池 一.使用ContentProvi ...

  8. 2014 BDTC 参会有感

    中国大数据技术大会(Big Data Technology Conference,BDTC)是目前国内最具影响.规模最大的大数据领域的技术盛会.大会的前身是Hadoop中国云计算大会(Hadoop i ...

  9. Swift中switch强大的模式匹配

    不少人觉得Swift中switch语句和C或C++,乃至ObjC中的差不多,此言大谬! 让本猫带领大家看一下Swift中switch语句模式匹配的威力. 所谓模式匹配就是利用一定模式(比如couple ...

  10. 我的第一个RootKit,支持XP、Vista、Win7、Win8 RTM 32位

    只有写过一个BootKit,才能比较深刻的理解其整个过程与机制,也能加深对Windows系统引导各个过程的熟悉和理解. 我写的这个bootkit,暂时还没想到一个比较好的名字,它 1.  支持xp到w ...