导语
我们在写程序的时候,一个无法避免的步骤就是配置文件的编写,有了配置文件,就要有相应的加载机制,比如读取配置文件到实体中,配置文件因为语法简单,具有灵活性,在程序中被广泛的使用,如今流行的有xml,json,yml等类型的配置文件,这一篇我们主要了解在Micro框架中是如何加载我们的配置文件。
导包
"github.com/micro/go-micro/config"
"github.com/micro/go-micro/config/source/file"
两个函数
第一个:func file.NewSource(opts ...source.Option) source.Source
使用这个函数可以实现我们对配置文件的加载,具体如何使用呢?让我们来看一个实例:
首先编写一个配置文件config.json
{
"hosts": {
"database": {
"name": "JSON",
"address": "10.0.0.1",
"port": 3306
}
}
}
编写一个main.go
,可以看到source.Option
参数由file.WithPath()
读取了配置文件进行了返回。
func main(){
// 加载配置文件
if err := config.Load(file.NewSource(
file.WithPath("./config/config.json"),
)); err != nil {
fmt.Println(err)
return
}
}
第二个func Get(path ...string) reader.Value
我们将要使用这个函数对配置文件的值读取出来。同样使用上面的配置文件。我们进行读取,从下面的函数中可以看出来,首先需要定义一个实体,然后对配置文件读出赋值操作。
// 定义我们的额数据结构
type Host struct {
Name string `json:"name"`
Address string `json:"address"`
Port int `json:"port"`
}
var host Host
if err := config.Get("hosts", "database").Scan(&host); err != nil {
fmt.Println(err)
return
}
现在我们测试一下,main.go
源码如下
func main() {
// 加载配置文件
if err := config.Load(file.NewSource(
file.WithPath("./config/config.json"),
// file.WithPath("./config/config.yml"),
)); err != nil {
fmt.Println(err)
return
}
// 定义我们的额数据结构
type Host struct {
Name string `json:"name"`
Address string `json:"address"`
Port int `json:"port"`
}
var host Host
if err := config.Get("hosts", "database").Scan(&host); err != nil {
fmt.Println(err)
return
}
fmt.Println(host.Name, host.Address, host.Port)
}
输出结果,可以看出我们轻松读取了我们的配置文件。
PS F:\micolearn\day03\micro-config> go run .\main.go
JSON 10.0.0.1 3306
疑问一?
在上面的json文件中明明是一个结构体中包含了另一个结构体,name、address、port的值应该在Database结构体中,为什么读取的时候,放在了Host结构体中?
在
func Get(path ...string) reader.Value
的参数中,我们可以注意到这是一个可变参数,我们可以传入无限个字符串,使用一个结构体,是Micro的取巧方式,上述代码代表取出hosts层级下的database的属性,只要在Host中可以做转换即可以转换。当然我们也可以用下面的方式做。
type HostAddress struct {
Database `json:"database"`
}
type Database struct {
Name string `json:"name"`
Address string `json:"address"`
Port int `json:"port"`
}
var hostthree HostAddress
if err := config.Get("hostthree").Scan(&hostthree); err != nil {
fmt.Println(err)
return
}
fmt.Println(hostthree.Database)
最后的打印结果是一个结构体
{JSON 10.0.0.1 3306}
疑问二?
我们可不可以不用嵌套这个结构体呢?
当然可以,这时候我们只需要在参数中传一个参数就行了,如下
{
"hosttwo": {
"name": "JSON",
"address": "10.0.0.1",
"port": 3306
}
}
读取,我们同样直接使用Host结构体
var hosttwo Host
if err := config.Get("hosttwo").Scan(&hosttwo); err != nil {
fmt.Println(err)
return
}
fmt.Println(hosttwo.Name, hosttwo.Address, hosttwo.Port)
打印测试后的结果
JSON 10.0.0.1 3306
疑问三?
以上都是比较简单的结构体,如果换成比较复杂的结构体,比如嵌套一个数组,也可以吗?
当然可以,其实在赋值的时候,我们不需要管结构体的内容,如果可以匹配到相应的值,就可以直接赋值。现在我们编写一个json文件
{
"hostfour": [
{
"name": "JSON",
"address": "10.0.0.1",
"port": 3306
},
{
"name": "JSON",
"address": "10.0.0.1",
"port": 3306
},
{
"name": "JSON",
"address": "10.0.0.1",
"port": 3306
}
]
}
同样编写我们的main.go,我们同样使用之前的Host结构体,从下面的函数体可以看出,我们仅仅改变了定义变量,定义成数组的类型进行存储。其它的根本不需要任何改变。
type Host struct {
Name string `json:"name"`
Address string `json:"address"`
Port int `json:"port"`
}
func main(){
// 加载配置文件
if err := config.Load(file.NewSource(
file.WithPath("./config/config.json"),
// file.WithPath("./config/config.yml"),
)); err != nil {
fmt.Println(err)
return
}
var hostfour []Host
if err := config.Get("hostfour").Scan(&hostfour); err != nil {
fmt.Println(err)
return
}
fmt.Println(hostfour)
}
测试结果,可以看出成功打印了我们的值
[{JSON 10.0.0.1 3306} {JSON 10.0.0.1 3306} {JSON 10.0.0.1 3306}]
非常感谢你保持着耐心读完这篇文章,我是陌无崖,一个专注于Golang后端开发的互联网从业人员,熟悉RabbitMQ,Docker,微服务等,获取更多知识分享,文章末尾扫码关注,每日推送,准时获取更多分享。
推荐阅读
- 开发环境搭建(持续更新中)
- RabbitMQ系列笔记介绍篇
- Golang中Modle包的使用
- goriila context深入学习笔记
- Go Context深入学习笔记
- 基于Nginx和Consul构建高可用及自动发现的Docker服务架构
- 关于log日志的深入学习笔记
本文欢迎转载,转载请联系作者,谢谢!
- 公众号【常更新】:陌无崖
- GitHub:https://github.com/yuwe1
- 博客地址【定期更新】:https://mowuya.cn/
有疑问加站长微信联系(非本文作者)