一文带你读懂Micro框架如何读取配置文件

不忘初心,砥砺前行

作者 | 陌无崖

转载请联系授权

导语

我们在写程序的时候,一个无法避免的步骤就是配置文件的编写,有了配置文件,就要有相应的加载机制,比如读取配置文件到实体中,配置文件因为语法简单,具有灵活性,在程序中被广泛的使用,如今流行的有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,微服务等,获取更多知识分享,文章末尾扫码关注,每日推送,准时获取更多分享。

END

今日推荐阅读

RabbitMQ系列笔记广播模式和路由模式 RabbitMQ系列笔记入门篇

RabbitMQ系列笔记work模式

RabbitMQ系列笔记work模式

protoc语法详解及结合grpc定义服务

Golang中Model的使用

基于Nginx和Consul构建高可用及自动发现的Docker服务架构

原文发布于微信公众号 - 陌无崖(gh_ebbdb61f463e)

原文发表时间:2019-08-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券