在go中使用json作为主要的配置格式
最近在用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作为主要的配置格式的更多相关文章
- jquery 解析数据库中的json日期为正常的格式
//在action从后台数据库中请求获得日期以后,得到的是json格式的数据,因此要解析才能显示在前台1.在jsp页面写的代码如下:<html> <script> Date.p ...
- C#中Newtonsoft.Json 序列化和反序列化 时间格式
步骤 引用 using Newtonsoft.Json; using Newtonsoft.Json.Converters; 格式配置 IsoDateTimeConverter timeFormat ...
- 如何正确的使用json?如何在.Net中使用json?
什么是json json是一种轻量级的数据交换格式,由N组键值对组成的字符串,完全独立于语言的文本格式. 为什么要使用json 在很久很久以前,调用第三方API时,我们通常是采用xml进行数据交互,但 ...
- C#中的Json的序列化和反序列化
Json是一种通用的数据格式,我们在数据交换的时候,经常会用到,下面介绍c#中的json序列化和反序列化,当然也可用在asp.net,silverlight,wpf中.我们在下面实例讲解如何进行Jso ...
- SpringMVC中使用Json传数据
在web项目中使用Json进行数据的传输是非常常见且有用的,在这里介绍下在SpringMVC中使用Json传数据的一种方法,在我的使用中,主要包括下面四个部分(我个人喜好使用maven这类型工具进行项 ...
- PHP中生成json信息的方法
<?php //php中生成json信息 //json_encode(数组/对象) $color = array('red','blue','green'); //[索引数组] echo jso ...
- 【ASP.NET Web API教程】6.2 ASP.NET Web API中的JSON和XML序列化
谨以此文感谢关注此系列文章的园友!前段时间本以为此系列文章已没多少人关注,而不打算继续下去了.因为文章贴出来之后,看的人似乎不多,也很少有人对这些文章发表评论,而且几乎无人给予“推荐”.但前几天有人询 ...
- 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 ...
- JMeter中返回Json数据的处理方法
Json 作为一种数据交换格式在网络开发,特别是 Ajax 与 Restful 架构中应用的越来越广泛.而 Apache 的 JMeter 也是较受欢迎的压力测试工具之一,但是它本身没有提供对于 Js ...
随机推荐
- android高德地图网络路径实现自定义marker并点击弹出自定义窗口
android中使用地图的地方随处可见,今天记录一下网络路径生成自定义marker,点击标记弹出自定义的窗口(在这里使用的是高德地图) 在这里我们使用Grilde去加载网络图片,因为这个简直太方便了! ...
- 小程序敏感信息解密-java
/** * AES解密 * @param content 密文 * @return * @throws InvalidAlgorithmParameterException * @throws NoS ...
- Junit4 java.lang.Exception: No runnable methods
出现如下错误: java.lang.Exception: No runnable methods at org.junit.runners.BlockJUnit4ClassRunner.validat ...
- Arrays的二分查找
二分查找也称为折半查找,是对有序元素查找的一种算法,在查找的过程中,不断的将搜索长度减半,因此效率不错.Java的JDK提供了二分法查找的算法,使用的方法是Arrays.binarySearch(). ...
- Ruby方法参数默认值的一个小技巧在Rails中的应用
我们需要生成一个gravatar格式的html.image标示,于是写了如下方法: def gravatar_for(user) gravatar_id = Digest::MD5::hexdiges ...
- 初识在Spring Boot中使用JPA
前面关于Spring Boot的文章已经介绍了很多了,但是一直都没有涉及到数据库的操作问题,数据库操作当然也是我们在开发中无法回避的问题,那么今天我们就来看看Spring Boot给我们提供了哪些疯狂 ...
- leetcode 5 Longest Palindromic Substring--最长回文字符串
问题描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...
- solr界面
1.1 界面功能介绍 1.1.1 Analysis
- Compass实战 站内搜索
今天早上打算对这两天学习的Lucene以及Compass总结一下,想来想去,还是写个小项目来验证最好了.于是就有了今天的这篇文章.难易程度适合对于Compass或者Lucene刚入门的童鞋,大牛看到后 ...
- LuaHotUpdate原理
LuaHotUpdate原理(金庆的专栏)项目地址:https://github.com/asqbtcupid/lua_hotupdate只更新函数,不更新数据.主页上有个动画演示.限Windows平 ...