最近在用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. angular-cli学习笔记 快速创建代码模板

    组件: ng g component component/demo 服务: ng g service service/news 然后在app.module.ts里引入 ng g service ser ...

  2. c#下winform的ftp上传

    /* FTPFactory.cs Better view with tab space=4 Written by Jaimon Mathew (jaimonmathew@rediffmail.com) ...

  3. Spring Boot Cache Redis缓存

    1.集成MyBatis 1.1.引入maven依赖 1.2.生成Mapper 具体可以看MyBatis Generator官网 http://www.mybatis.org/generator/run ...

  4. Python之禅及其翻译

    凡是用过 Python的人,基本上都知道在交互式解释器中输入 import this 就会显示 Tim Peters 的 The Zen of Python,但它那偈语般的语句有点令人费解,所以我想分 ...

  5. 13.QT-QMainWindow组件使用

    QMainWindow介绍 主窗口是与用户进行长时间交互的顶层窗口,比如记事本 主窗口通常是应用程序启动后显示的第一个窗口 QMainWindow是Qt中主窗口的基类,继承于QWidget,如下图所示 ...

  6. Fiddler实现对手机抓包

    工具 && 前提条件: 1. 安装了Fiddler的PC一台 2. 手机一部 3. 手机和PC是在同一个局域网内,或者至少能够联通,即手机的流量能够转发到PC端上能够被其捕获 PC端 ...

  7. Linux下使用MD5加密BASE64加密

    这里以字符串123456为例子,它的md5密文值为:e10adc3949ba59abbe56e057f20f883e 这里以1.txt为需要被加密的文件. 一. 用oppnssl md5 加密字符串和 ...

  8. PHP echo和print 语句

    PHP  echo 和 print 语句 在 PHP 中有两个基本的输出方式: echo 和 print. 本章节中我们会详细讨论两个语句的用法,并在实例中演示如何使用 echo 和 print. P ...

  9. Unity3D开发注意事项

    最近给组里定Unity开发注意事项,参考了@陆泽西在群里分享的[前端开发规范],结合自己工作中的经验,整理一下,下面不少条款都是我们要求在开发中必须遵守的. 资源: 图片统一为png格式,纹理属性:T ...

  10. Hibernate使用自定义脚本替换注解或者xml文件中的自动生成表结构

    本文作者:苏生米沿 本文地址:http://blog.csdn.net/sushengmiyan/article/details/50534361 我们都清楚,可以使用hibernate的metada ...