GoFrame的配置管理由gcfg组件实现,gcfg组件的所有方法是并发安全的。gcfg组件采用接口化设计,默认提供的是基于文件系统的接口实现。
GoFrame
gcfg
使用方式:
import "github.com/gogf/gf/v2/os/gcfg"
接口文档:
https://pkg.go.dev/github.com/gogf/gf/v2/os/gcfg
gcfg组件具有以下显著特性:
yaml/toml/json/xml/ini/properties
框架配置组件支持多种常用的数据格式,但在后续的示例代码中均使用yaml数据格式来做演示说明。在使用中,请随意使用习惯的数据格式不用局限于官网示例使用的yaml数据格式。例如,在业务项目模板中提供的是config.yaml配置文件模板(因为默认模板只能提供一种啊),您也可以直接修改为config.toml或者config.ini等支持的数据格式,配置组件也能自动根据文件名后缀识别读取。
yaml
config.yaml
config.toml
config.ini
强哥我在看示例代码,没有找到加载config下的config.example.toml的相关逻辑,这块怎么实现的啊。还有就是也没看到数据库相关的配置在哪初始化连接的。
你这家伙,分明就是不专心看书嘛,示例代码第一行不就是了吗, SetFileName()
还有个问题,配置文件之间有没有继承关系,比如我有一套基础配置,又根据ENV不同会重写一些IP或者端口之类的配置,例如base.toml 和 dev.toml,base里定义了各个环境中通用的配置, env.toml定义各个环境中需要重写的配置,这样有办法支持么
目前不支持呢。不过有考虑后续会将gcfg的核心功能做成接口化,这样开发者可以自定义配置读取。
这个配置文件继承 你看这样行不行?
1.读取base.toml
2.读取dev.toml
3.合并2个配置文件的内容
我们做法是只读dev.toml ,里面有一个关键字作为他的父文件,以此类推。感觉也还好
能具体说说是怎么操作的吗?谢谢🙏
可以参考 viper,不过它的实现机制是按优先级逐个读每个文件里的 key,匹配到就退出,不利于整结构读取。
反馈一个文档错误
假如我们的执行程序文件为main,那么可以通过以下方式修改配置管理器的配置文件目录(Linux下):
main
Linux
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{}) }
文件的相对路径没有设置对的, 它会报这样的错:
[ERRO] [gcfg] cannot find config file "config.fuck.toml" in resource manager or the following paths
1. C:\Users\huang\Desktop\GFdemo22. C:\Users\huang\Desktop\GFdemo2\config
我的配置文件是gfdemo2/config/fuck.toml, 灵活思考,把
// var ConfigObj2 = g.Cfg().SetFileName("config.fuck.toml")
改成
var ConfigObj2 = g.Cfg().SetFileName("fuck.toml")
就好了.
另外, 好像这个方法不能添加绝对路径的配置文件来着?
评论区编辑器没有markdown...
支持相对路径和绝对路径,任何开发语言在设置相对路径的时候新手往往容易出错。
是你配置错了。
g.Cfg().SetFileName("config.fuck.toml") 是找Desktop\GFdemo2\config.fuck.toml 或 Desktop\GFdemo2\config\config.fuck.toml
g.Cfg().SetFileName("fuck.toml") 是找Desktop\GFdemo2\fuck.toml 或 Desktop\GFdemo2\config\fuck.toml
好的,我看看,因为是初次接触所以有很多知其然不知其所以然的地方,哈哈
请问在程序运行中切换了配置文件。能刷新已经使用的 g.DB()的配置吗?
g.DB()
配置会自动刷新到内存中。但数据库比较特殊一些,如果采用dao操作连接对象不会刷新,需要重新进程。如果是采用g.DB()操作数据库,会刷新连接对象。
dao
在做自动化安装功能,将 server 和 生成工具做再一个exe里,出现dao起始加载不到config的问题,才有此疑问。
目前打包默认config到exe。在install时生成默认config 并用shell 重新执行程序解决问题
请问平滑重启功能应该可以刷新 DAO 连接对象吧?我看平滑重启那一部分说的是重启后 pid 会改变。
有老哥解答下吗,怎么这么难用啊。在win打了win,linux的包,win双击能正常启动,端口没问题。linux启动端口是80。找了一遍说什么配置,然后又启动加配置。如下:
[root@localhost office]# ./officeView --gf.gcfg.file /root/app/office/config.toml 2021/07/27 10:11:24 init ...2021-07-27 10:11:24.223 [FATA] SetServerRoot failed: cannot find file/folder "public" in following paths:1. /root/app/office Stack:1. office_view/router.init.0 C:/Users/Administrator/IdeaProjects/xxx/svn/office_view/router/router.go:10
特么的,烦死了,不想学了,gf版本为v1.6.4,
1.我想问问如何改端口呀,打出来的win双击端口是配置里边的。linux该怎么改
2.还有我想问问在win上打的包,linux运行为啥会出现win的路径。
算了,我歇逼了
新建一个public空目录试试
C:/Users/Administrator/IdeaProjects/xxx/svn/office_view/router/router.go:10
这个路径是错误堆栈信息,是打包时候的文件路径,用来告诉你在哪个文件哪一行出问题了。
把心静下来慢慢学。
这代码都是自动生成的func init() { s := g.Server() //第10行 s.Group("/", func(group *ghttp.RouterGroup) { group.GET("/hello", api.Hello.Index) group.GET("/officeView/:name", api.Office.Get) })}
你可能没细看文档项目配置。
也需要好好学习一下如何阅读错误信息,错误处理-堆栈特性。
其实错误提示也挺明显的,就是在linux下运行的时候没有找到你的配置文件中所指定的serverRoot文件夹。
serverRoot = "public"
等于我打包的时候还得把config下的配置文件拷贝到public下边呀?
在运行的目录下面建一个public目录
我去,怎么端口还是80啊,没效果
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE ----------|---------|---------|--------|-------------------|------------------------------------------|------------- default | default | :80 | GET | /hello | office_view/app/api.(*helloApi).Index-fm |
你这没改动端口, 可不就是默认80
请问配置文件中的数据库密码,能像java那样,加密吗?
试了下,Linux环境下要使用 export GF_GCFG_FILE=config.prod.toml; ./main 配置文件才生效。
我刚开始学习GoFrame,请问现在支不支持在配置文件里使用环境变量?谢谢
v2可以,哈哈哈
if len(masterList) < 1 { return nil, gerror.NewCode(gcode.CodeInvalidConfiguration, "at least one master node configuration's need to make sense") } if len(slaveList) < 1 { slaveList = masterList } if master { return getConfigNodeByWeight(masterList), nil } else { return getConfigNodeByWeight(slaveList), nil }
if node, err := getConfigNodeByGroup(groupName, true); err == nil { 这里调用上面代码块的函数,传入的master参数始终为true,没法获取slave的配置吧?
支持配置文件自动检测热更新特性,这个 热更新 怎么配置,我搜索了一下没找到示例,是我的姿势不对吗?
直接改配置文件的内容就可以
k8s部署的,直接GF_GCFG_FILE注入到deployment即可
郭强 请问可以支持hocon格式的配置文件吗? https://github.com/lightbend/config/blob/master/HOCON.md
看起来不难,欢迎一起参与开源贡献哈。
反馈一个配置热更比较严重的bug,gf在运行过程中,配置被copy覆盖,会出现取到第三种状态数据的问题。用例如下
当前目录config.toml config.toml.bak go.mod go.sum main.go
main.goimport ( "context" "fmt" "time" "github.com/fsnotify/fsnotify" "github.com/gogf/gf/v2/frame/g" "github.com/spf13/viper")func main() { //testViper() testGfConfig()}func testViper() { logger := g.Log() viper.SetConfigName("config") // 配置文件名字,注意没有扩展名 viper.SetConfigType("toml") // 如果配置文件的名称中没有包含扩展名,那么该字段是必需的 viper.AddConfigPath("./") // 配置文件的路径 err := viper.ReadInConfig() // 查找并读取配置文件 if err != nil { panic(fmt.Errorf("Fatal error config file: %w \n", err)) } viper.WatchConfig() viper.OnConfigChange(func(e fsnotify.Event) { logger.Info(context.TODO(), "Config file changed:", e.Name) }) tk := time.NewTicker(time.Nanosecond) defer tk.Stop() for range tk.C { version := viper.GetString("version") logger.Info(context.TODO(), version) }}func testGfConfig() { logger := g.Log() tk := time.NewTicker(time.Nanosecond) defer tk.Stop() for range tk.C { version, err := g.Cfg().Get(context.TODO(), "version") if err != nil { panic(err) } logger.Info(context.TODO(), version) }}config.tomlversion=1[logger]Path = "console.log"Level = "all"Stdout = trueCtxKeys = ["TraceId"]config.toml.bak的version=2go.mod go 1.18require ( github.com/fsnotify/fsnotify v1.7.0 github.com/gogf/gf/v2 v2.5.6 github.com/spf13/viper v1.17.0)运行代码,然后执行以下命令$: cp -rf config.toml.bak config.toml你猜怎么着?2023-11-09 19:10:50.089 [INFO] 12023-11-09 19:10:50.089 [INFO]2023-11-09 19:10:50.089 [INFO]2023-11-09 19:10:50.089 [INFO]2023-11-09 19:10:50.089 [INFO]2023-11-09 19:10:50.089 [INFO]2023-11-09 19:10:50.089 [INFO]2023-11-09 19:10:50.089 [INFO]2023-11-09 19:10:50.089 [INFO]2023-11-09 19:10:50.089 [INFO]2023-11-09 19:10:50.089 [INFO] 22023-11-09 19:10:50.089 [INFO] 22023-11-09 19:10:50.090 [INFO] 2程序居然读出了第三种状态。viper是没有这个问题的。
请提个issue或者pr哈。
issue
pr
缺少个保存配置功能, 虽然说保存配置会重载配置, 可能会影响性能, 但是这个需求还是有的.
通过 inotify 接收文件变化通知,而非轮询,性能应该没什么影响吧
不知道, 反正挺缺的, 我现在配置只能用 go-ini/ini, 不过用了gf, 就更加喜欢啥都用gf自带的. 要是有就更好了.
42 Comments
ayamzh
强哥我在看示例代码,没有找到加载config下的config.example.toml的相关逻辑,这块怎么实现的啊。还有就是也没看到数据库相关的配置在哪初始化连接的。
黄昌淮
你这家伙,分明就是不专心看书嘛,示例代码第一行不就是了吗, SetFileName()
ayamzh
还有个问题,配置文件之间有没有继承关系,比如我有一套基础配置,又根据ENV不同会重写一些IP或者端口之类的配置,例如base.toml 和 dev.toml,base里定义了各个环境中通用的配置, env.toml定义各个环境中需要重写的配置,这样有办法支持么
郭强
目前不支持呢。不过有考虑后续会将
gcfg
的核心功能做成接口化,这样开发者可以自定义配置读取。刘羽禅
这个配置文件继承 你看这样行不行?
1.读取base.toml
2.读取dev.toml
3.合并2个配置文件的内容
ayamzh
我们做法是只读dev.toml ,里面有一个关键字作为他的父文件,以此类推。感觉也还好
LeeEcho
能具体说说是怎么操作的吗?谢谢🙏
杨延庆
可以参考 viper,不过它的实现机制是按优先级逐个读每个文件里的 key,匹配到就退出,不利于整结构读取。
刘羽禅
反馈一个文档错误
假如我们的执行程序文件为
main
,那么可以通过以下方式修改配置管理器的配置文件目录(Linux
下):看这段文字描述,我在main.go文件中加入了,这行代码,然而并不生效
然后我在boot.go中添加,是可以正常工作的
黄昌淮
文件的相对路径没有设置对的, 它会报这样的错:
[ERRO] [gcfg] cannot find config file "config.fuck.toml" in resource manager or the following paths
1. C:\Users\huang\Desktop\GFdemo2
2. C:\Users\huang\Desktop\GFdemo2\config
我的配置文件是gfdemo2/config/fuck.toml, 灵活思考,把
// var ConfigObj2 = g.Cfg().SetFileName("config.fuck.toml")
改成
var ConfigObj2 = g.Cfg().SetFileName("fuck.toml")
就好了.
另外, 好像这个方法不能添加绝对路径的配置文件来着?
评论区编辑器没有markdown...
郭强
支持相对路径和绝对路径,任何开发语言在设置相对路径的时候新手往往容易出错。
海亮
是你配置错了。
g.Cfg().SetFileName("config.fuck.toml") 是找Desktop\GFdemo2\config.fuck.toml 或 Desktop\GFdemo2\config\config.fuck.toml
g.Cfg().SetFileName("fuck.toml") 是找Desktop\GFdemo2\fuck.toml 或 Desktop\GFdemo2\config\fuck.toml
黄昌淮
好的,我看看,因为是初次接触所以有很多知其然不知其所以然的地方,哈哈
杨率帅
请问在程序运行中切换了配置文件。能刷新已经使用的
g.DB()
的配置吗?郭强
配置会自动刷新到内存中。但数据库比较特殊一些,如果采用
dao
操作连接对象不会刷新,需要重新进程。如果是采用g.DB()
操作数据库,会刷新连接对象。杨率帅
在做自动化安装功能,将 server 和 生成工具做再一个exe里,出现dao起始加载不到config的问题,才有此疑问。
目前打包默认config到exe。在install时生成默认config 并用shell 重新执行程序解决问题
Rainshaw
请问平滑重启功能应该可以刷新 DAO 连接对象吧?我看平滑重启那一部分说的是重启后 pid 会改变。
鼻屎拌饭加蛋
有老哥解答下吗,怎么这么难用啊。在win打了win,linux的包,win双击能正常启动,端口没问题。linux启动端口是80。找了一遍说什么配置,然后又启动加配置。如下:
[root@localhost office]# ./officeView --gf.gcfg.file /root/app/office/config.toml
2021/07/27 10:11:24 init ...
2021-07-27 10:11:24.223 [FATA] SetServerRoot failed: cannot find file/folder "public" in following paths:
1. /root/app/office
Stack:
1. office_view/router.init.0
C:/Users/Administrator/IdeaProjects/xxx/svn/office_view/router/router.go:10
特么的,烦死了,不想学了,gf版本为v1.6.4,
1.我想问问如何改端口呀,打出来的win双击端口是配置里边的。linux该怎么改
2.还有我想问问在win上打的包,linux运行为啥会出现win的路径。
鼻屎拌饭加蛋
算了,我歇逼了
LeeEcho
新建一个public空目录试试
海亮
C:/Users/Administrator/IdeaProjects/xxx/svn/office_view/router/router.go:10
这个路径是错误堆栈信息,是打包时候的文件路径,用来告诉你在哪个文件哪一行出问题了。
把心静下来慢慢学。
鼻屎拌饭加蛋
海亮
你可能没细看文档项目配置。
也需要好好学习一下如何阅读错误信息,错误处理-堆栈特性。
其实错误提示也挺明显的,就是在linux下运行的时候没有找到你的配置文件中所指定的serverRoot文件夹。
鼻屎拌饭加蛋
等于我打包的时候还得把config下的配置文件拷贝到public下边呀?
海亮
在运行的目录下面建一个public目录
鼻屎拌饭加蛋
我去,怎么端口还是80啊,没效果
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
----------|---------|---------|--------|-------------------|------------------------------------------|-------------
default | default | :80 | GET | /hello | office_view/app/api.(*helloApi).Index-fm |
小陈
你这没改动端口, 可不就是默认80
yzl
请问配置文件中的数据库密码,能像java那样,加密吗?
LeeEcho
试了下,Linux环境下要使用 export GF_GCFG_FILE=config.prod.toml; ./main 配置文件才生效。
Raymond
我刚开始学习GoFrame,请问现在支不支持在配置文件里使用环境变量?谢谢
aries
v2可以,哈哈哈
JKing
feiyu
支持配置文件自动检测热更新特性,这个 热更新 怎么配置,我搜索了一下没找到示例,是我的姿势不对吗?
糖水不加糖
直接改配置文件的内容就可以
guoliang_gl_zhou
k8s部署的,直接GF_GCFG_FILE注入到deployment即可
Cheney
郭强 请问可以支持hocon格式的配置文件吗? https://github.com/lightbend/config/blob/master/HOCON.md
郭强
看起来不难,欢迎一起参与开源贡献哈。
cloud
反馈一个配置热更比较严重的bug,gf在运行过程中,配置被copy覆盖,会出现取到第三种状态数据的问题。用例如下
郭强
请提个
issue
或者pr
哈。小陈
缺少个保存配置功能, 虽然说保存配置会重载配置, 可能会影响性能, 但是这个需求还是有的.
杨延庆
通过 inotify 接收文件变化通知,而非轮询,性能应该没什么影响吧
小陈
不知道, 反正挺缺的, 我现在配置只能用 go-ini/ini, 不过用了gf, 就更加喜欢啥都用gf自带的. 要是有就更好了.