当前位置: 首页 > 科技观察

Go云原生实战:如何添加应用配置模块

时间:2023-03-16 23:22:19 科技观察

Part1简介我们在自己写程序的时候,通常会直接在源码中写一些重要的配置项,比如:服务器监听的端口,使用的名称数据库和端口号,HTTP请求超时时长...但是,如果我们尝试将这个项目开源给别人使用,用户使用的数据库的用户名和名称可能与你的不一样,您甚至可能不得不为他们的服务器使用另一个数据库。一个港口。如果你还给数据库设置了密码,为了安全,就更不可能在代码中泄露信息了。因此,在本节中,我们将介绍如何将配置模块添加到我们的运动应用程序中。Part2添加配置模块在许多开源项目中,配置是通过键值数据结构来处理的。在实际应用中,你经常会发现一个暴露配置选项的类(或结构),这个类经常会解析文件并为每个选项分配一个值。应用程序通常会建议命令行选项来调整配置。2.1定义Configuration接口接下来我们为应用程序添加配置能力,这样上面提到的很多配置就不需要在代码文件中定义了。1、创建sports/config文件夹,新建config.go文件,写入如下代码:bool)GetBool(名称字符串)(configValuebool,foundbool)GetFloat(namestring)(configValuefloat64,foundbool)GetStringDefault(name,defValstring)(configValuestring)GetIntDefault(namestring,defValint)(configValueint)GetBoolDefault(namestring,defValbool)(configValuebool)GetFloatDefault(namestring,defValfloat64)(configValuefloat64)GetSection(sectionNamestring)(sectionConfiguration,foundbool)}可以看出,Configuration接口定义了获取配置的方法设置,支持获取字符串string、数字int、浮点型float64、布尔型bool的值:GetString()GetInt()GetBool()GetFloat()还有一组方法可以提供一个默认值值:GetStringDefault()GetIntDefault()GetBoolDefault()GetFloatDefault()配置数据将允许嵌套配置部分,这将使用GetSection()方法实现。2.2查看一个基本的JSON配置文件配置可以从命令行获取。当然,更好的方法是将配置保存在文件中,由应用程序自动解析。文件的格式取决于应用程序的需要。如果您需要具有级别和层次结构的复杂配置(以Windows注册表方式),那么您可能需要考虑JSON、YAML或XML等格式。让我们看一个示例JSON配置文件:{"server":{"host":"localhost","port":80},"database":{"host":"localhost","username":"myUsername","password":"abcdefgh"}}上面的JSON配置文件定义了server服务器和database数据库信息。但是在本文中,基于上一节介绍的日志功能,为了简化操作,我们只是简单的配置了我们的日志和主要功能信息。2、在sports目录下,新建一个config.json文件,写入如下内容:{"logging":{"level":"debug"},"main":{"message":"Hello,Let'sGo!Hello从配置文件”}}这个配置文件定义了两个配置部分,分别命名为logging和main:logging部分包含单个字符串配置设置,名为levelmain的部分包含单个字符串配置设置,名为message的文件显示配置文件使用的基本结构。JSON配置文件中,注意引号和逗号符合JSON文件的格式要求。许多人经常犯错误。2.3实现Configuration接口为了实现Configuration接口,我们会在sports/config文件夹下创建一个config_default.go文件,然后写入如下代码:packageconfigimport"strings"typeDefaultConfigstruct{configDatamap[string]interface{}}func(c*DefaultConfig)get(namestring)(resultinterface{},foundbool){data:=c.configDatafor_,key:=rangestrings.Split(name,":"){结果,found=data[key]ifnewSection,ok:=result.(map[string]interface{});ok&&found{data=newSection}else{return}}return}func(c*DefaultConfig)GetSection(namestring)(sectionConfiguration,foundbool){value,found:=c.get(name)如果找到{ifsectionData,好的:=value.(map[string]interface{});ok{section=&DefaultConfig{configData:sectionData}}}return}func(c*DefaultConfig)GetString(namestring)(resultstring,foundbool){value,found:=c.get(name)如果找到{result=value.(string)}return}func(c*DefaultConfig)GetInt(namestring)(resultint,foundbool){value,found:=c.get(name)iffound{result=int(value.(float64))}return}func(c*DefaultConfig)GetBool(名称字符串)(resultbool,foundbool){value,found:=c.get(name)如果找到{result=value.(bool)}return}func(c*DefaultConfig)GetFloat(namestring)(resultfloat64,foundbool){value,found:=c.get(name)iffound{result=value.(float64)}return}DefaultConfig结构使用map实现Configuration接口,嵌套的配置部分也用map表示,即就是,上面的代码中:typeDefaultConfigstruct{configDatamap[string]interface{}}单个配置可以通过sectionname和settingname分隔,例如:logging:level,或者使用mapmap来映射根据key或Value的名称,比如logging。2.4定义接收默认值的方法为了处理来自配置文件的值,我们在sports/config文件夹下创建一个config_default_fallback.go文件:packageconfigfunc(c*DefaultConfig)GetStringDefault(name,valstring)(结果字符串){结果,ok:=c.GetString(name)if!ok{result=val}return}func(c*DefaultConfig)GetIntDefault(namestring,valint)(resultint){结果,ok:=c.GetInt(name)if!ok{result=val}return}func(c*DefaultConfig)GetBoolDefault(namestring,valbool)(resultbool){result,ok:=c.GetBool(name)if!ok{结果=val}return}func(c*DefaultConfig)GetFloatDefault(namestring,valfloat64)(resultfloat64){result,ok:=c.GetFloat(name)if!ok{result=val}return}2.5将函数定义为从配置文件加载数据在sports/config文件夹下新建config_json.go文件加载JSON数据,写入如下代码:packageconfigimport("encoding/json""os""strings")funcLoad(filenamestring)(configConfiguration,errerror){vardata[]bytedata,err=os.ReadFile(filename)iferr==nil{解码器:=json.NewDecoder(strings.NewReader(string(data)))m:=map[string]interface{}{}err=decoder.Decode(&m)iferr==nil{config=&DefaultConfig{configData:m}}}return}Load函数读取一个文件的内容,将其中包含的JSON文件解析成一个map,并使用map创建一个DefaultConfig值关于Go是如何处理JSON文件的,有兴趣的可以搜索我之前的文章:《Go 语言入门很简单:Go 语言解析JSON》Part3使用Configuration配置系统为了获取新添加的配置系统的日志级别信息,我们将返回logging文件夹在上一节的default_create.go文件中,写入如下代码:Configuration)Logger{//使用配置varlevelLogLevel=DebugifconfigLevelString,found:=cfg.GetString("logging:level");发现{level=LogLevelFromString(configLevelString)}flags:=log.Lmsgprefix|log.Ltimereturn&DefaultLogger{minLevel:level,loggers:map[LogLevel]*log.Logger{Trace:log.New(os.Stdout,"TRACE",flags),Debug:log.New(os.Stdout,"DEBUG",flags),信息:log.New(os.Stdout,"INFO",flags),警告:log.New(os.Stdout,"WARNING",flags),致命:log.New(os.Stdout,"FATAL",flags),},triggerPanic:true,}}funcLogLevelFromString(valstring)(级别LogLevel){switchstrings.ToLower(val){case"debug":level=Debugcase"information":level=Informationcase"warning":level=Warningcase"fatal":level=Fatalcase"none":level=None}return}在JSON中没有表示iota值的好方法,所以我们使用字符串并定义LogLevelFromString()函数将配置设置转换为LogLevel的值最后,我们更新main()函数加载和应用配置数据,并使用配置系统读取它输出的信息,更改main.go文件如下。packagemainimport(//"fmt""sports/config""sports/logging")//funcwriteMessage(loggerlogging.Logger){////fmt.Println("Let'sGo")//logger.Info("Let'sGo,logger")//}//funcmain(){//varloggerlogging.Logger=logging.NewDefaultLogger(logging.Information)//writeMessage(logger)//}funcwriteMessage(loggerlogging.Logger,cfgconfig.Configuration){section,ok:=cfg.GetSection("main")ifok{message,ok:=section.GetString("message")ifok{logger.Info(message)}else{logger.Panic(“找不到配置设置”)}}else{logger.Panic(“找不到配置部分”)}}funcmain(){varcfgconfig.Configurationvarerrerrorcfg,err=config.Load("config.json")iferr!=nil{panic(err)}varloggerlogging.Logger=logging.NewDefaultLogger(cfg)writeMessage(logger,cfg)}至此,我们的配置是通过NewDefaultLogger()函数从config.json文件中获取的通过执行Configuration,最后读取日志级别设置。writeMessage()函数显示了配置部分的使用,提供组件所需的设置,尤其是当需要具有不同配置的多个实例时,每个实例都可以在其自己的部分中定义。最终的项目结构如图所示:最后,我们在终端编译运行我们的全部代码:$gorun.17:20:46INFOHello,Let'sGo!Hellofromtheconfigfile整个代码会输出并打印出配置文件中的信息,如图:Part4Summary本文介绍了项目配置文件的由来和重要性,从零到一编写代码,并成功将应用配置功能添加到我们的Web项目中。并结合上一节的日志功能,进行了测试。事实上,在Go开源项目中,有一个非常著名的开源配置包:Viper,它为Go应用项目提供了完整的配置解决方案,帮助我们快速处理各类配置需求和配置文件格式。目前GitHubStar数高达21k,这个项目会在后续的文章中介绍。