Go开发学习 | 如何快速读取json/yaml/ini等格式的配置文件使用示例

欢迎关注「全栈工程师修炼指南」公众号

点击 👇 下方卡片 即可关注我哟!

设为星标⭐每天带你 基础入门 到 进阶实践 再到 放弃学习

  花开堪折直须折,莫待无花空折枝 


作者主页:[ https://www.weiyigeek.top ]  

博客:[ https://blog.weiyigeek.top ]

作者安全运维学习答疑交流群:请关注公众号回复【学习交流群


文章目录:

0x00 前言简述

0x01 常用模块

    • encoding/json 模块 - json 配置文件解析

    • gopkg.in/ini.v1 模块 - ini 配置文件解析

    • gopkg.in/yaml.v3 模块 - yaml 配置文件解析

    • spf13/viper 模块 - 配置文件解析终结者

    • 原生map结构 - properties 配置文件解析

0x00 前言简述

描述: 作为开发者相信对应用程序的配置文件并不陌生吧,例如 Java Spring Boot 里的 class 目录中程序配置,当然go语言相关项目也是可以根据配置文件的格式内容进行读取的,常规的配置文件格式有 json、ini、yaml (个人推荐)、properties 等,我们可以使用其为程序配置一些初始化的可变参数,例如 数据库字符串链接以及认证密码等等。

好,下面作者将依次从json、ini、以及yaml、properties 等顺序进行讲解。


0x01 常用模块

encoding/json 模块 - json 配置文件解析

config.json 配置文件示例

{"app": {"app_name": "hello-gin","app_mode": "dev","app_host": "localhost","app_port": "8080","app_secret": "weiyigeek.top"},"log":{"log_name": "app","log_path": "/logs","log_age": "180","log_rotation_time": "24"},"db": {"mysql": {"mysql_user": "root","mysql_pass": "123456","mysql_addr": "localhost","mysql_port": "3306","mysql_database": "test"},"redis": {"redis_addr": "localhost","redis_port": "6379","redis_database": "9","redis_pass": "123456"}} 
}

LoadJSONConfig函数进行JSON配置文件读取

package configimport ("encoding/json""log""os"
)// 读取 JSON 配置文件
// JSON 配置文件结构体
type AppJSONConfig struct {AppName   string `json:"app_name"`AppMode   string `json:"app_mode"`AppHost   string `json:"app_host"`AppPort   string `json:"app_port"`AppSecret string `json:"app_secret"`
}type LogJSONConfig struct {LogPath         string `json:"log_path"`LogName         string `json:"log_name"`LogAge          string `json:"log_age"`LogRotationTime string `json:"log_rotation_time"`
}type DbMySQLJSONConfig struct {User     string `json:"mysql_user"`Pass     string `json:"mysql_pass"`Addr     string `json:"mysql_addr"`Port     string `json:"mysql_port"`Database string `json:"mysql_database"`
}
type DbRedisJSONConfig struct {Addr     string `json:"redis_addr"`Port     string `json:"redis_port"`Pass     string `json:"redis_pass"`Database string `json:"redis_database"`
}
type DbJSONConfig struct {Mysql DbMySQLJSONConfig `json:"mysql"`Redis DbRedisJSONConfig `json:"redis"`
}type JSONConfig struct {App AppJSONConfig `json:"app"`Log LogJSONConfig `json:"log"`Db  DbJSONConfig  `json:"db"`
}func LoadJSONConfig(path string) *JSONConfig {// 定义局部变量var Config JSONConfig// 打开配置文件f, err := os.Open(path)if err != nil {log.Printf("Open config file failed!")panic(err)}// 程序结束时关闭打开的文件defer f.Close()// NewDecoder创建一个从file读取并解码json对象的*Decoder,解码器有自己的缓冲,并可能超前读取部分json数据。decoder := json.NewDecoder(f)// Decode从输入流读取下一个json编码值并保存在v指向的值里(关键点)decode_err := decoder.Decode(&Config)if err != nil {panic(decode_err)}return &Config
}

函数执行入口:

// 声明当前文件属于哪个包,如果是主文件,则写成main
package main// 导入gin包
import ("fmt""hello-gin/util/config"
)func main() {conf := config.LoadJSONConfig()fmt.Print(conf, "\n")fmt.Println("----------------------------------")fmt.Println("应用名称", conf.App.AppName)fmt.Println("应用密钥", conf.App.AppSecret)
}

执行结果:

> go run .\main.go
&{{hello-gin dev localhost 8080 weiyigeek.top} {/logs app debug} {{root 123456 localhost 3306 test} {localhost 6379 123456 9}}}
----------------------------------
应用名称 hello-gin
应用密钥 weiyigeek.top

gopkg.in/ini.v1 模块 - ini 配置文件解析

在Go中读取INI文件,我们可以使用名为go-ini的第三方库(a third-party library),它是一个非常方便、高效的go配置文件操作库。

模块下载: go get -v -u gopkg.in/ini.v1

config.ini 配置文件示例:

[app]
name="hellogin"
mode="dev"
host="localhost"
port=8080
secret="weiyigeek"[log]
name="ginDemo"
path="D:/Study/Project/Go/hello-gin/logs"
maxage=180
rotation_time=24
rotation_size=100[mysql]
host=192.168.2.2
port=3306
user=weiyigeek
pass=123456
database=weiyigeek[redis]
host=192.168.2.6
port=6379
pass=weiyigeek.top
database=10

LoadINIConfig 读取ini配置文件函数

package configimport ("fmt""gopkg.in/ini.v1"
)// 创建ini配置文件中相关的字段结构体
type AppINIConfig struct {AppName   string `ini:"name"`AppMode   string `ini:"mode"`AppHost   string `ini:"host"`AppPort   int    `ini:"port"`AppSecret string `ini:"secret"`
}type LogINIConfig struct {LogPath         string `ini:"path"`LogName         string `ini:"name"`LogAge          int    `ini:"age"`LogRotationTime int    `ini:"rotation_time"`LogRotationSize int    `ini:"rotation_size"`
}type DbMysqlINIConfig struct {User     string `ini:"user"`Pass     string `ini:"pass"`Host     string `ini:"addr"`Port     int    `ini:"port"`Database string `ini:"database"`
}type DbRedisINIConfig struct {Host     string `ini:"addr"`Port     int    `ini:"port"`Pass     string `ini:"pass"`Database string `ini:"database"`
}type INIConfig struct {App     AppINIConfig     `ini:"app"`Log     LogINIConfig     `ini:"log"`DbMysql DbMysqlINIConfig `ini:"mysql"`DbRedis DbMysqlINIConfig `ini:"redis"`
}func LoadINIConfig(path string) *INIConfig {// 0.实例化结构体config := &INIConfig{}// 1.加载配置文件cfg, err := ini.Load(path)if err != nil {fmt.Println("配置文件读取错误,请检查文件路径:", err)panic(err)}// 2.读取配置文件各章节下的KV配置值,并设定默认默认值。config.App.AppName = cfg.Section("app").Key("name").String()config.App.AppMode = cfg.Section("app").Key("mode").MustString("dev")config.App.AppHost = cfg.Section("app").Key("host").MustString("localhost")config.App.AppPort = cfg.Section("app").Key("port").MustInt(8080)config.App.AppSecret = cfg.Section("app").Key("secret").String()config.Log.LogName = cfg.Section("log").Key("name").String()config.Log.LogPath = cfg.Section("log").Key("path").String()config.Log.LogAge = cfg.Section("log").Key("maxage").MustInt(180)config.Log.LogRotationSize = cfg.Section("log").Key("rotation_time").MustInt(24)config.Log.LogRotationTime = cfg.Section("log").Key("rotation_size").MustInt(100)config.DbMysql.Host = cfg.Section("mysql").Key("host").String()config.DbMysql.Port = cfg.Section("mysql").Key("port").MustInt(3306)config.DbMysql.User = cfg.Section("mysql").Key("user").String()config.DbMysql.Pass = cfg.Section("mysql").Key("pass").String()config.DbMysql.Database = cfg.Section("mysql").Key("database").String()config.DbRedis.Host = cfg.Section("redis").Key("host").String()config.DbRedis.Port = cfg.Section("redis").Key("port").MustInt(6379)config.DbRedis.Pass = cfg.Section("redis").Key("pass").String()config.DbRedis.Database = cfg.Section("redis").Key("database").String()return config
}

main 函数入口调用

// 声明当前文件属于哪个包,如果是主文件,则写成main
package main// 导入gin包
import ("fmt""hello-gin/util/config"
)func main() {confINI := config.LoadINIConfig("configs/config.ini")fmt.Println(confINI)fmt.Println("App : ", confINI.App)fmt.Println("Log : ", confINI.Log)fmt.Println("Database :", confINI.DbRedis.Database)
}

执行结果:

go run .\main.go
&{{hellogin dev localhost 8080 weiyigeek} {D:/Study/Project/Go/hello-gin/logs ginDemo 180 100 24} {weiyigeek 123456 192.168.2.2 3306 weiyigeek} { weiyigeek.top 192.168.2.6 6379 10}}
App :  {hellogin dev localhost 8080 weiyigeek}
Log :  {D:/Study/Project/Go/hello-gin/logs ginDemo 180 100 24}
Database : 10

gopkg.in/yaml.v3 模块 - yaml 配置文件解析

描述: gopkg.in/yaml.v3 包使Go程序能够轻松地对yaml值进行编码和解码, 它是作为juju项目的一部分在Canonical中开发的,基于著名的libyaml C库的纯Go端口,可以快速可靠地解析和生成YAML数据。

项目地址: https://github.com/go-yaml/yaml

模块包下载: go get -v -u gopkg.in/yaml.v3

config.yaml 配置文件示例

app:name: "hellogin"mode: "dev"host: "localhost"port: "8080"secret: "weiyigeek"
log:name: "ginDemo"path: "D:/Study/Project/Go/hello-gin/logs"maxage: 180rotation_time: 24rotation_size: 100
db:mysql:host: 192.168.2.2port: 3306user: weiyigeekpass: 123456database: weiyigeekredis:host: 192.168.2.6port: 3306pass: weiyigeek.topdatabase: 10
user:user:- weiyigeek- geekermqtt:host: 192.168.2.7:1883username: weiyigeekpassword: weiyigeek.top

LoadYAMLConfig 函数读取yaml配置文件

package configimport ("fmt""io/ioutil""log""gopkg.in/yaml.v3"
)// 读取yaml配置文件
// YAML 配置文件结构体
type AppYAMLConfig struct {AppName   string `yaml:"name"`AppMode   string `yaml:"mode"`AppHost   string `yaml:"host"`AppPort   string `yaml:"port"`AppSecret string `yaml:"secret"`
}type LogYAMLConfig struct {LogPath         string `yaml:"path"`LogName         string `yaml:"name"`LogAge          string `yaml:"age"`LogRotationTime string `yaml:"rotation_time"`LogRotationSize string `yaml:"rotation_size"`
}type DbMySQLYAMLConfig struct {User     string `yaml:"user"`Pass     string `yaml:"pass"`Addr     string `yaml:"addr"`Port     string `yaml:"port"`Database string `yaml:"database"`
}
type DbRedisYAMLConfig struct {Addr     string `yaml:"addr"`Port     string `yaml:"port"`Pass     string `yaml:"pass"`Database string `yaml:"database"`
}
type DbYAMLConfig struct {Mysql DbMySQLYAMLConfig `yaml:"mysql"`Redis DbRedisYAMLConfig `yaml:"redis"`
}type MqttYAMLconfig struct {Host     string `yaml:"host"`Username string `yaml:"username"`Password string `yaml:"password"`
}type UserYAMLconfig struct {User []string       `yaml:"user"`Mqtt MqttYAMLconfig `yaml:"mqtt"`
}type YAMLConfig struct {App  AppYAMLConfig  `yaml:"app"`Log  LogYAMLConfig  `yaml:"log"`Db   DbYAMLConfig   `yaml:"db"`User UserYAMLconfig `yaml:"user"`
}func LoadYAMLConfig(path string) *YAMLConfig {// 定义局部变量config := &YAMLConfig{}// 打开并读取yaml配置文件yamlFile, err := ioutil.ReadFile(path)if err != nil {log.Printf("Open config.yaml failed!")panic(err)}// 使用yaml中Unmarshal方法,解析yaml配置文件并绑定定义的结构体err = yaml.Unmarshal(yamlFile, config)if err != nil {log.Printf("yaml config file Unmarsha failed!")panic(err)}return config
}

入口函数:

// 声明当前文件属于哪个包,如果是主文件,则写成main
package main// 导入gin包
import ("fmt""hello-gin/util/config"
)func main() {confYAML := config.LoadYAMLConfig("configs/config.yaml")fmt.Print(confYAML, "\n")fmt.Println("--------------------------------------------------------------")fmt.Println("应用用户", confYAML.User.User)fmt.Println("应用名称", confYAML.App.AppName)fmt.Println("应用密钥", confYAML.App.AppSecret)fmt.Println("MySQL账号密码:", confYAML.Db.Mysql.User, confYAML.Db.Mysql.Pass)
}

执行结果:

&{{hellogin dev localhost 8080 weiyigeek} {D:/Study/Project/Go/hello-gin/logs ginDemo  24 100} {{weiyigeek 123456  3306 weiyigeek} { 3306 weiyigeek.top 10}} {[weiyigeek geeker] {192.168.2.7:1883 weiyigeek weiyigeek.top}}}
--------------------------------------------------------------
应用用户 [weiyigeek geeker]
应用名称 hellogin
应用密钥 weiyigeek

spf13/viper 模块 - 配置文件解析终结者

描述: 在前面实践中作者分别用了三种模块包以原生包针对四种不同配置的文件,那到底有没有引入一个包就可以全部解析的呢? 既然这么问,那答案显然是可以的, 那就是今天的主人公 viper 项目地址: github.com/spf13/viper

viper 适用于Go应用程序(包括[Twelve-Factor App)的完整配置解决方案,它被设计用于在应用程序中工作,并且可以处理所有类型的配置需求和格式,它支持以下特性:

  • 设置默认值以及显式配置值

  • 从JSON、TOML、YAML、HCL、envfile和Java properties格式的配置文件读取配置信息

    var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}

  • 实时监控和重新读取配置文件(可选)

  • 从环境变量中读取

  • 从远程配置系统(etcd或Consul)读取并监控配置变化

    var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore"}

  • 从命令行参数读取配置

  • 从buffer读取配置

Viper 优先级

  • 显示调用Set设置值

  • 命令行参数(flag)

  • 环境变量

  • 配置文件

  • key/value存储

  • 默认值

PS: 目前Viper配置的键(Key)是大小写不敏感的。

模块下载安装: go get github.com/spf13/viper

常用函数

  •  Get(key string) : interface{}

  •  GetBool(key string) : bool

  •  GetFloat64(key string) : float64

  •  GetInt(key string) : int

  •  GetIntSlice(key string) : []int

  •  GetString(key string) : string

  •  GetStringMap(key string) : map[string]interface{}

  •  GetStringMapString(key string) : map[string]string

  •  GetStringSlice(key string) : []string

  •  GetTime(key string) : time.Time

  •  GetDuration(key string) : time.Duration

  •  IsSet(key string) : bool

  •  AllSettings() : map[string]interface{}

温馨提示: 每一个Get方法在找不到值的时候都会返回零值, 为了检查给定的键是否存在,提供了IsSet()方法.

参考地址: https://github.com/spf13/viper/blob/master/README.md


偷偷的告诉你哟?极客全栈修炼】微信小程序已经上线了,

可直接在微信里面直接浏览博主博客了哟,后续将上线更多有趣的小工具。


常规使用

// # 如果没有通过配置文件、环境变量、远程配置或命令行标志(flag)设置键,则默认值非常有用。
viper.SetDefault("ContentDir", "content")
viper.SetDefault("LayoutDir", "layouts")
viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})// # Viper支持JSON、TOML、YAML、HCL、envfile和Java properties格式的配置文件
// 方式1
viper.SetConfigFile("config.yaml")     // 指定配置文件路径
viper.AddConfigPath("/etc/appname/")   // 查找配置文件所在的路径// 方式2
viper.SetConfigName("config")          // 配置文件名称(无扩展名)
viper.SetConfigType("yaml")            // 如果配置文件的名称中没有扩展名,则需要配置此项
viper.AddConfigPath("/etc/appname/")   // 查找配置文件所在的路径
viper.AddConfigPath("$HOME/.appname")  // 多次调用以添加多个搜索路径
viper.AddConfigPath(".")               // 还可以在工作目录中查找配置// # 通过 ReadInConfig 函数,寻找配置文件并读取,操作的过程中可能会发生错误,如配置文件没找到,配置文件的内容格式不正确等;
if err := viper.ReadInConfig(); err != nil {if _, ok := err.(viper.ConfigFileNotFoundError); ok {// 配置文件未找到错误;如果需要可以忽略} else {// 配置文件被找到,但产生了另外的错误}
} else {// 配置文件找到并成功解析
}// # Viper 覆盖设置
viper.Set("Verbose", true)
viper.Set("LogFile", LogFile)// # 通过 ReadInConfig 函数,寻找配置文件并读取,操作的过程中可能会发生错误,如配置文件没找到,配置文件的内容格式不正确等;
fmt.Println(viper.Get("mysql"))     // map[port:3306 url:127.0.0.1]
fmt.Println(viper.Get("mysql.url")) // 127.0.0.1// # 使用viper函数获取嵌套的键的值
{"host": {"address": "localhost","port": 5799},"datastore": {"mysql": {"host": "127.0.0.1","port": 3306}}
}viper.GetString("datastore.mysql.host") // (返回 "127.0.0.1")// # 获取子树值
app:cache1:max-items: 100item-size: 64cache2:max-items: 200item-size: 80subv := viper.Sub("app.cache1")// # viper加载完配置信息后使用结构体变量保存配置信息
type Config struct {Port    int    `mapstructure:"port"`Version string `mapstructure:"version"`
}
var Conf = new(Config)
// 将读取的配置信息保存至全局变量Conf
if err := viper.Unmarshal(Conf); err != nil {panic(fmt.Errorf("unmarshal conf failed, err:%s \n", err))
}// # 使用WatchConfig监控配置文件变化
viper.WatchConfig()
// 注意!!!配置文件发生变化后要同步到全局变量Conf
viper.OnConfigChange(func(in fsnotify.Event) {fmt.Println("配置文件被修改了")if err := viper.Unmarshal(Conf); err != nil {panic(fmt.Errorf("unmarshal conf failed, err:%s \n", err))}
})

示例1.Viper支持Cobra库中使用的Pflag绑定并输出

package mainimport ("flag""fmt""github.com/spf13/pflag""github.com/spf13/viper"
)func main() {// 使用标准库 "flag" 包flag.Int("flagname", 1234, "help message for flagname")// pflag 包可以通过导入这些 flags 来处理flag包定义的flags, pflag 包可以通过导入这些 flags 来处理flag包定义的flagspflag.CommandLine.AddGoFlagSet(flag.CommandLine)pflag.Parse()// viper 绑定到标志viper.BindPFlags(pflag.CommandLine)// 从 viper 检索值i := viper.GetInt("flagname")fmt.Println(i)  // 1234
}

示例2.使用viper读取yaml并存放在结构体中

configs\prod.yaml 配置文件

app:name: "hellogin"mode: "dev"host: "localhost"port: "8080"secret: "weiyigeek"version: "v1.2.0"
log:name: "ginDemo"path: "D:/Study/Project/Go/hello-gin/logs"maxage: 180rotation_time: 24rotation_size: 100
db:mysql:host: 192.168.2.2port: 3306user: weiyigeekpass: 123456database: weiyigeekredis:host: 192.168.2.6port: 3306pass: weiyigeek.topdatabase: 10

代码示例:

// go get -v -u  gopkg.in/yaml.v3
package mainimport ("fmt""github.com/fsnotify/fsnotify""github.com/spf13/viper"
)// YAML 配置文件KV结构体
type AppYAMLConfig struct {AppName    string `mapstructure:"name"`AppMode    string `mapstructure:"mode"`AppHost    string `mapstructure:"host"`AppPort    string `mapstructure:"port"`AppSecret  string `mapstructure:"secret"`AppVersion string `mapstructure:"version"`
}type LogYAMLConfig struct {LogPath         string `mapstructure:"path"`LogName         string `mapstructure:"name"`LogAge          string `mapstructure:"age"`LogRotationTime string `mapstructure:"rotation_time"`LogRotationSize string `mapstructure:"rotation_size"`
}type DbMySQLYAMLConfig struct {User     string `mapstructure:"user"`Pass     string `mapstructure:"pass"`Addr     string `mapstructure:"addr"`Port     string `mapstructure:"port"`Database string `mapstructure:"database"`
}
type DbRedisYAMLConfig struct {Addr     string `mapstructure:"addr"`Port     string `mapstructure:"port"`Pass     string `mapstructure:"pass"`Database string `mapstructure:"database"`
}
type DbYAMLConfig struct {Mysql DbMySQLYAMLConfig `mapstructure:"mysql"`Redis DbRedisYAMLConfig `mapstructure:"redis"`
}type MqttYAMLconfig struct {Host     string `mapstructure:"host"`Username string `mapstructure:"username"`Password string `mapstructure:"password"`
}type YAMLConfig struct {App AppYAMLConfig `mapstructure:"app"`Log LogYAMLConfig `mapstructure:"log"`Db  DbYAMLConfig  `mapstructure:"db"`
}// viper对象示例化与配置文件读取
func NewConfig(name string) *viper.Viper {// 设置实例化viper对象vp := viper.New()// 设置配置文件名,没有后缀vp.SetConfigName(name)// 设置读取文件格式为: yamlvp.SetConfigType("yaml")// 设置配置文件目录(可以设置多个,优先级根据添加顺序来)vp.AddConfigPath("./configs/")// 读取配置文件并解析if err := vp.ReadInConfig(); err != nil {if _, ok := err.(viper.ConfigFileNotFoundError); ok {fmt.Printf("配置文件未找到!%v\n", err)return nil} else {fmt.Printf("找到配置文件,但是解析错误,%v\n", err)return nil}}// 绑定返回结构体对象return vp
}func main() {// 实例化 vp 对象vp := NewConfig("prod")// 获取指定key值fmt.Println("Version : ", vp.Get("app.version"))// 获取指定节值返回map数据类型fmt.Println(vp.GetStringMap("app"))v := vp.GetStringMap("app")fmt.Println("version : ", v["version"], "\n")// 将获取到的数据绑定到结构体conf := new(YAMLConfig)if err := vp.Unmarshal(conf); err != nil {fmt.Printf("解析错误: %v\n", err)panic(err)}fmt.Println(conf, "\n")// 监控配置文件的变化// # 使用WatchConfig监控配置文件变化vp.WatchConfig()// 注意!!!配置文件发生变化后要同步到全局变量Confvp.OnConfigChange(func(in fsnotify.Event) {fmt.Println("配置文件被修改了")if err := vp.Unmarshal(conf); err != nil {panic(fmt.Errorf("unmarshal conf failed, err:%s \n", err))}})fmt.Println(vp)
}

执行结果:

go run .\main.go
Version :  v1.2.0
map[host:localhost mode:dev name:hellogin port:8080 secret:weiyigeek version:v1.2.0]
version :  v1.2.0&{{hellogin dev localhost 8080 weiyigeek v1.2.0} {D:/Study/Project/Go/hello-gin/logs ginDemo  24 100} {{weiyigeek 123456  3306 weiyigeek} { 3306 weiyigeek.top 10}}}&{. [D:\Study\Project\Go\hello-gin\configs] 0x1235c48 [] prod D:\Study\Project\Go\hello-gin\configs\prod.yaml yaml 420  {false false false false false false false false false false false false false false false []    false <nil> 0 false 
false} false <nil> false map[app:map[host:localhost mode:dev name:hellogin port:8080 secret:weiyigeek version:v1.2.0] db:map[mysql:map[database:weiyigeek host:192.168.2.2 pass:123456 port:3306 user:weiyigeek] redis:map[database:10 host:192.168.2.6 pass:weiyigeek.top port:3306]] log:map[maxage:180 name:ginDemo path:D:/Study/Project/Go/hello-gin/logs rotation_size:100 rotation_time:24]] map[] map[] map[] map[] map[] map[] false 0xfa25a0 {} 0xc000066860 0xc000066880}

原生map结构 - properties 配置文件解析

properties 配置文件

appName=hellogin
appMode=dev
appHost=localhost
appPort=8080
appSecret="WeiyiGeek"logName="ginDemo"
logPath="D:/Study/Project/Go/hello-gin/logs"
logMaxage=180
logRotationTime=24
logRotationSize=100

亲,文章就要看完了,不关注一下作者吗?

632e101430f89c01015a7a5c77399174.jpeg

LoadPropConfig 函数读取properties配置文件

package configimport ("bufio""fmt""io""os""strings"
)var properties = make(map[string]string)func LoadPropConfig(path string) map[string]string {propFile, err := os.OpenFile(path, os.O_RDONLY, 0666)if err != nil {fmt.Println("打开 config.properties 配置文件失败!")panic(err)}propReader := bufio.NewReader(propFile)for {prop, err := propReader.ReadString('\n')if err != nil {if err == io.EOF {break}}// 此处注意不要出现Yoda conditions问题if (len(prop) == 0) || (prop == "\n") {continue}properties[strings.Replace(strings.Split(prop, "=")[0], " ", "", -1)] = strings.Replace(strings.Split(prop, "=")[1], " ", "", -1)}return properties
}

函数调用主入口

// 声明当前文件属于哪个包,如果是主文件,则写成main
package main// 导入gin包
import ("fmt""hello-gin/util/config"
)func main() {properties := config.LoadPropConfig("configs/config.properties")fmt.Println(properties)fmt.Print("AppName : ", properties["appName"])fmt.Println("LogPath : ", properties["logPath"])
}

执行结果:

$ go run .\main.go
map[appHost:localhostappMode:devappName:helloginappPort:8080appSecret:"WeiyiGeek"logMaxage:180logName:"ginDemo"logPath:"D:/Study/Project/Go/hello-gin/logs"logRotationTime:24
]
AppName : hellogin
LogPath :  "D:/Study/Project/Go/hello-gin/logs"

本文至此完毕,更多技术文章,尽情等待下篇好文!

原文地址: https://blog.weiyigeek.top/2023/4-18-731.html

如果此篇文章对你有帮助,请你将它分享给更多的人! 

da08b27ba0839b3cb43063f19b89b941.gif

bae338adcd377a020625e0b32bf8d857.png 学习书籍推荐 往期发布文章 1bbde2d4d5b4e63e07b1eff9ad1a4d8a.png

公众号回复【0008】获取【Ubuntu22.04安装与加固建脚本】

公众号回复【10001】获取【WinServer安全加固脚本】

公众号回复【1000】获取【PowerShell操作FTP脚本】

公众号回复【0015】获取【Jenkins学习之路汇总】

 热文推荐  

  • 容灾恢复 | 记一次K8S集群中etcd数据快照的备份恢复实践

  • 企业实践 | 如何从VMWare ESXi Shell中挂载以及拷贝NTFS或者FAT32分区格式的USB闪存驱动器

  • 奇技淫巧 | 快速提升网站权重,巧用GPT4自动化大数据生成关键字指数进行SEO排名优化

  • 网安等保-国产Linux操作系统银河麒麟KylinOS-V10SP3常规配置、系统优化与安全加固基线实践文档

欢迎长按(扫描)二维码 6361cf860831a9af5c33d7e664d62c92.gif取更多渠道哟!

0b496bbc294b3d7e09fd9fa0a74b7d94.jpeg8aa0248ba3bacd66e6a3e8ad4162050e.jpegd6c953cc34e42fbcf72c1f8e0284cba9.jpeg

303fe77ff5fa78609659b7c25172b739.gif

欢迎关注 【全栈工程师修炼指南】(^U^)ノ~YO

== 全栈工程师修炼指南 ==

微信沟通交流: weiyigeeker 

关注回复【学习交流群】即可加入【安全运维沟通交流小群

温馨提示: 由于作者水平有限,本章错漏缺点在所难免,希望读者批评指正,若有问题或建议请在文章末尾留下您宝贵的经验知识,或联系邮箱地址

master@weiyigeek.top 或 关注公众号 [全栈工程师修炼指南] 留言。

[全栈工程师修炼指南]  关注 企业运维实践、网络安全、系统运维、应用开发、物联网实战、全栈文章,尽在博客站点,谢谢支持!

点个【 赞 + 在 】看吧!

d094244d5fb67d033adf731685be3dc8.gif 点击【"阅读原文"】获取更多有趣的知识!   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/256603.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Kafka笔记

1. MQ产品对比 ActiveMQRabbitMQRocketMQKafkaEMQ公司/社区ApacheRabbit&#xff08;https://www.rabbitmq.com/&#xff09;阿里&#xff08;https://rocketmq.apache.org/&#xff09;Apache&#xff08;http://kafka.apache.org/ &#xff09;EMQ X(https://www.emqx.cn/)开…

以支付宝为例,聊聊Web安全的三个攻防姿势

我们最常见的Web安全攻击有以下几种 XSS 跨站脚本攻击CSRF 跨站请求伪造clickjacking 点击劫持/UI-覆盖攻击 下面我们来逐个分析 一、XSS 跨站脚本攻击 跨站脚本攻击&#xff08;Cross Site Scripting&#xff09;&#xff0c;为了不和层叠样式表&#xff08;Cascading Styl…

详解.NET IL代码

IL是什么&#xff1f; Intermediate Language &#xff08;IL&#xff09;微软中间语言 C#代码编译过程&#xff1f; C#源代码通过LC转为IL代码&#xff0c;IL主要包含一些元数据和中间语言指令&#xff1b; JIT编译器把IL代码转为机器识别的机器代码。如下图 语言编译器&am…

桌面宠物大全

无聊收集的: 桌面宠物大全 24个桌面宠物 类似种种,总之花了很多精力,将网上能见到的基本都收录了。其中:无需汉化的25个、盛华汉化的255个、未能汉化的32个,共312个。 看看自己朝夕相处的电脑桌面,还是一如既往的一片寂静,太没有气氛了。今天就给大家介绍几个好玩的桌…

为什么职场中35岁之后很难找到合适的工作?

(点击即可收听) 为什么职场中35岁之后很难找到合适的工作 无论是初入职场还是,职场多年的老司机,都听过一个35岁危机的一个话题 无论是企业还是一些招聘者,针对35,甚至就是30的人,充满了不是这样,就是那样的偏见的理由 每个公司都喜欢有激情,有想法,有干劲的年轻人,无论哪个公司…

读数据压缩入门笔记03_VLC

1. 概率、熵与码字长度 1.1. 数据压缩的目的 1.1.1. 给定一个数据集中的符号&#xff0c;将最短的编码分配给最可能出现的符号 1.2 1.2.1. 当P(A)P(B)&#xff0c;也就是两个符号等可能出现时&#xff0c;数据集对应的熵取最大值LOG2&#xff08;符号的个数&#xff09;&…

《计算机组成原理》唐朔飞 第7章 指令系统 - 学习笔记

写在前面的话&#xff1a;此系列文章为笔者学习计算机组成原理时的个人笔记&#xff0c;分享出来与大家学习交流。使用教材为唐朔飞第3版&#xff0c;笔记目录大体与教材相同。 网课 计算机组成原理&#xff08;哈工大刘宏伟&#xff09;135讲&#xff08;全&#xff09;高清_…

HTTPX从入门到放弃

1. 什么是HTTPX&#xff1f; HTTPX是一款Python栈HTTP客户端库&#xff0c;它提供了比标准库更高级别、更先进的功能&#xff0c;如连接重用、连接池、超时控制、自动繁衍请求等等。HTTPX同时也支持同步和异步两种方式&#xff0c;因此可以在同步代码和异步代码中通用。 HTTP…

FPGA纯vhdl实现XGMII接口10G万兆网UDP协议 配合10G Ethernet PCS/PMA使用 提供工程源码和技术支持

目录 1、前言2、我这里已有的UDP方案3、详细设计方案本 10G-UDP 协议栈功能和性能描述本 10G-UDP 协议栈设计框图用户发送AXIS接口描述用户接收AXIS接口描述控制接口描述XGMII接口描述 4、vivado工程详解10G-UDP协议栈10G Ethernet PCS/PMA IP核 5、上板调试验证并演示6、福利&…

iOS 13修复了FaceTime最大的烦恼之一

黑客技术 点击右侧关注&#xff0c;了解黑客的世界&#xff01; Java开发进阶 点击右侧关注&#xff0c;掌握进阶之路&#xff01; Linux编程 点击右侧关注&#xff0c;免费入门到精通&#xff01; iOS 13 第三个开发者 beta 版本增加了一个新功能&#xff0c;可以让用户在 Fac…

多人聊天、预约会议,FaceTime登录Windows和Android系统

整理 | Carol 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 在一年一度的WWDC苹果开发者盛会中&#xff0c;Apple除了宣布引入iOS15以外&#xff0c;还宣布将面向Windows和Android用户开放FaceTime。而过去&#xff0c;这项能力只能在iOS和Mac设备上试用。 Face…

iPhone曝严重漏洞,用户接听FaceTime前或被“监听”!

作者 | 琥珀 出品 | AI科技大本营&#xff08;ID: rgznai100&#xff09; 近日&#xff0c;据 9to5Mac 等多家外媒报道&#xff0c;苹果手机 FaceTime 一项重大漏洞被曝光&#xff0c;该漏洞可以让用户通过 FaceTime 群聊功能&#xff08;Group FaceTime&#xff09;打电话给任…

黑苹果facetime_如何在消息或FaceTime中添加或删除电话号码

黑苹果facetime If you have an iPhone and a Mac or iPad, you can link your phone number to your iCloud account to send and receive calls and messages from the same number on both devices. 如果您拥有iPhone和Mac或iPad&#xff0c;则可以将电话号码链接到iCloud帐…

苹果 iOS 15 正式发布

本文转载自IT之家 IT之家 6 月 8 日消息 今日凌晨&#xff0c;苹果召开 WWDC21 全球开发者大会&#xff0c;正式公布了全新 iOS 15 系统。 IT之家了解到&#xff0c;在 iOS 15 系统中&#xff0c;苹果带来了全新 FaceTime 与通知界面&#xff0c;并对照片、天气、钱包、地图等…

【苹果imessage相册推信】黑apple苹果经常出现FaceTime群设备推和Imessage群发设备推

黑色苹果经常出现FaceTime和Imessage&#xff0c;无法正常登录。 需要正常登录&#xff0c;你需要提到3码&#xff0c;一些帖子甚至复制在真正的白色苹果机上方。 但实际上&#xff0c;我希望上述服务将正常使用&#xff0c;我们需要补充SMUUID&#xff0c;BoardSerialNumber和…

FaceTime 在苹果电脑macOS与iPhone iOS上视频聊天配置步骤

FaceTime 在macOS与iPhone视频聊天配置步骤 前提&#xff0c;毫无疑问&#xff0c;你要有Apple ID。 1&#xff0c;在苹果电脑&#xff0c;到Applications目录下打开运行FaceTime 2&#xff0c;还是在电脑&#xff0c;输入你的Apple ID 3&#xff0c;还是在电脑&#xff0c;这里…

iMessage, Facetime 解决办法

不需要白苹果三码&#xff0c;亲测可用&#xff1a;原帖地址&#xff1a; https://www.reddit.com/r/hackintosh/comments/2wohwn/getting_imessage_working_on_10102_generating/ 感谢原帖的大神&#xff0c;感谢搜索。如果你得到一个错误信息&#xff0c;那么你很辛运。这意味…

【苹果推软件】安装OS imessage和faceTime

推荐内容IMESSGAE相关 作者推荐内容参考此文档来操作 *** 点击即可查看作者要求内容信息作者推荐内容1.参考此文档来操作 *** 点击即可查看作者要求内容信息作者推荐内容2.参考此文档来操作 *** 点击即可查看作者要求内容信息作者推荐内容3.参考此文档来操作 *** 点击即可查看…

如何解决FaceTime在苹果Mac上不起作用的问题?

由于多种原因&#xff0c;FaceTime无法在Mac上正常工作。在某些情况下&#xff0c;该应用程序行为不正常或将您注销&#xff0c;因此您将无法使用FaceTime。同样&#xff0c;如果您在使用相机或麦克风时遇到问题&#xff0c;Mac的日期和时间不正确&#xff0c;或者互联网连接状…

黑苹果解决 iMessage 与 Facetime 以及苹果三码的问题

教程来自http://www.heimac.net 若有侵权&#xff0c;及时私信我删除本文&#xff0c;再次感谢&#xff01; 作者&#xff1a;超级管理员 黑苹果经常出现Facetime 和 iMessage 无法正常登陆。需要正常登陆则需要所说的白苹果 3 码&#xff0c;有些帖子甚至已经到真正的白苹果机…