GoFrame的配置管理由gcfg模块实现,gcfg模块是并发安全的,仅提供配置文件读取功能,不提供数据写入/修改功能,支持的数据文件格式包括: JSONXMLYAML/YMLTOMLINI,项目中开发者可以灵活地选择自己熟悉的配置文件格式来进行配置管理。

使用方式

import "github.com/gogf/gf/os/gcfg"

接口文档

https://godoc.org/github.com/gogf/gf/os/gcfg

配置管理

配置文件

默认配置文件

默认读取的配置文件为config.tomltoml类型文件也是默认的、推荐的配置文件格式(语法参考 配置管理-TOML格式 章节),如果想要自定义文件格式,可以通过SetFileName方法修改默认读取的配置文件名称(如:config.json, cfg.yaml, cfg.xml, cfg.ini等等)。

如果是单例获取,有自动化文件类型检索的特性,具体请参考 配置管理-单例对象 章节。

例如,我们可以通过以下方式读取config.json配置文件中的数据库database配置项。

// 设置默认配置文件,默认的 config.toml 将会被覆盖
g.Cfg().SetFileName("config.json")
// 后续读取时将会读取到 config.json 配置文件内容,
g.Cfg().Get("database")

我们有两种方式进行配置文件的管理,使用全局的g.Cfg()获取单例对象(推荐),或者单独使用gcfg模块进行管理。

示例配置文件 config.toml

# 模板引擎目录
viewpath = "/home/www/templates/"
# MySQL数据库配置
[database]
    [[database.default]]
        host     = "127.0.0.1"
        port     = "3306"
        user     = "root"
        pass     = "123456"
        name     = "test1"
        type     = "mysql"
        role     = "master"
        charset  = "utf8"
        priority = "1"
    [[database.default]]
        host     = "127.0.0.1"
        port     = "3306"
        user     = "root"
        pass     = "123456"
        name     = "test2"
        type     = "mysql"
        role     = "master"
        charset  = "utf8"
        priority = "1"
# Redis数据库配置
[redis]
    disk  = "127.0.0.1:6379,0"
    cache = "127.0.0.1:6379,1"

注意:以上toml配置文件中的密码字段值123456使用了双引号进行包含,用以标识该密码字段为字符串类型,防止配置文件读取时自动转换为整型引起歧义。

默认文件修改

我们可以通过多种方式修改默认文件名称:

  1. 通过配置管理方法SetFileName修改。
  2. 修改命令行启动参数 - gf.gcfg.file
  3. 修改指定的环境变量 - GF_GCFG_FILE

假如我们的执行程序文件为main,那么可以通过以下方式修改配置管理器的配置文件目录(Linux下):

  1. 通过单例模式
     g.Cfg().SetFileName("config.prod.toml")
  2. 通过命令行启动参数
     ./main --gf.gcfg.file=config.prod.toml
  3. 通过环境变量(常用在容器中)
    • 启动时修改环境变量:
        GF_GCFG_FILE=config.prod.toml; ./main
    • 使用genv模块来修改环境变量:
        genv.Set("GF_GCFG_FILE", "config.prod.toml")

配置读取

gcfg包最大的特点是支持按层级获取配置数据,层级访问默认通过英文”.“号指定,其中pattern参数和 gjson (数据动态编解码)pattern参数一致。

例如针对以上config.toml配置文件内容的层级读取:

// /home/www/templates/
g.Cfg().Get("viewpath")

// 127.0.0.1:6379,1
g.Cfg().Get("redis.cache")

// test2
g.Cfg().Get("database.default.1.name")

配置修改

我们可以通过Set方法动态修改配置对象中的配置数据,Set方法定义如下:

func (c *Config) Set(pattern string, value interface{}) error

使用方式同 gjson (数据动态编解码) 模块。

配置目录

目录配置方法

gcfg配置管理器支持非常灵活的多目录自动搜索功能,通过SetPath可以修改目录管理目录为唯一的一个目录地址,同时,我们推荐通过AddPath方法添加多个搜索目录,配置管理器底层将会按照添加目录的顺序作为优先级进行自动检索。直到检索到一个匹配的文件路径为止,如果在所有搜索目录下查找不到配置文件,那么会返回失败。

默认目录配置

gcfg配置管理对象初始化时,默认会自动添加以下配置文件搜索目录:

  1. 当前工作目录及其下的config目录:例如当前的工作目录为/home/www时,将会添加/home/www/home/www/config
  2. 当前可执行文件所在目录及其下的config目录:例如二进制文件所在目录为/tmp时,将会添加/tmp/tmp/config
  3. 当前main源代码包所在目录及其下的config目录(仅对源码开发环境有效):例如main包所在目录为/home/john/workspace/gf-app时,将会添加/home/john/workspace/gf-app/home/john/workspace/gf-app/config

默认目录修改

我们可以通过以下方式修改配置管理器的配置文件搜索目录,配置管理对象将会只在该指定目录执行配置文件检索:

  1. 通过配置管理器的SetPath方法手动修改;
  2. 修改命令行启动参数 - gf.gcfg.path
  3. 修改指定的环境变量 - GF_GCFG_PATH

假如我们的执行程序文件为main,那么可以通过以下方式修改配置管理器的配置文件目录(Linux下):

  1. 通过单例模式
     g.Cfg().SetPath("/opt/config")
  2. 通过命令行启动参数
     ./main --gf.gcfg.path=/opt/config/
  3. 通过环境变量(常用在容器中)
    • 启动时修改环境变量:
        GF_GCFG_PATH=/opt/config/; ./main
    • 使用genv模块来修改环境变量:
        genv.Set("GF_GCFG_PATH", "/opt/config")

注意事项

大家都知道,在Golang里面,map/slice类型其实是一个”引用类型”(也叫”指针类型”),因此当你对这种类型的变量 键值对/索引项 进行修改时,会同时修改到其对应的底层数据。

从效率上考虑,gcfg包某些获取方法返回的数据类型为map/slice时,没有对齐做值拷贝,因此当你对返回的数据进行修改时,会同时修改gcfg对应的底层数据。

例如:

// For testing/example only.
content := `{"map":{"key":"value"}, "slice":[59,90]}`
gcfg.SetContent(content)
defer gcfg.RemoveContent()

m := g.Cfg().GetMap("map")
fmt.Println(m)

// Change the key-value pair.
m["key"] = "john"

// It changes the underlying key-value pair.
fmt.Println(g.Cfg().GetMap("map"))

s := g.Cfg().GetArray("slice")
fmt.Println(s)

// Change the value of specified index.
s[0] = 100

// It changes the underlying slice.
fmt.Println(g.Cfg().GetArray("slice"))

// output:
// map[key:value]
// map[key:john]
// [59 90]
// [100 90]

检测更新

配置管理器使用了缓存机制,当配置文件第一次被读取后会被缓存到内存中,下一次读取时将会直接从缓存中获取,以提高性能。同时,配置管理器提供了对配置文件的自动检测更新机制,当配置文件在外部被修改后,配置管理器能够即时地刷新配置文件的缓存内容。




Content Menu

  • No labels

6 Comments

  1. 强哥我在看示例代码,没有找到加载config下的config.example.toml的相关逻辑,这块怎么实现的啊。还有就是也没看到数据库相关的配置在哪初始化连接的。

  2. 还有个问题,配置文件之间有没有继承关系,比如我有一套基础配置,又根据ENV不同会重写一些IP或者端口之类的配置,例如base.toml 和 dev.toml,base里定义了各个环境中通用的配置, env.toml定义各个环境中需要重写的配置,这样有办法支持么

    1. 目前不支持呢。不过有考虑后续会将gcfg的核心功能做成接口化,这样开发者可以自定义配置读取。

    2. 这个配置文件继承    你看这样行不行?

      1.读取base.toml

      2.读取dev.toml

      3.合并2个配置文件的内容


      1. 我们做法是只读dev.toml ,里面有一个关键字作为他的父文件,以此类推。感觉也还好

  3. 反馈一个文档错误


    假如我们的执行程序文件为main,那么可以通过以下方式修改配置管理器的配置文件目录(Linux下):

    1. 通过单例模式
       g.Cfg().SetFileName("config.prod.toml")


    看这段文字描述,我在main.go文件中加入了,这行代码,然而并不生效

    然后我在boot.go中添加,是可以正常工作的

    // 用于应用初始化。
    func init() {
    	g.Config().SetFileName("config.prod.toml")
    	
    	s := g.Server()
    
    	//开启debug模式,打印更多调试信息,建议在开发环境开启
    	g.SetDebug(true)
    	s.Plugin(&swagger.Swagger{})
    }