当前位置:网站首页>go语言的ini文件配置读取
go语言的ini文件配置读取
2022-08-05 14:35:00 【ydl1128】
项目中我们可能经常要读取配置文件。那么如何读取自己写的配置文件呢?答案是反射。下面举例mysql的配置文件读取的具体操作代码。
1.首先建立myconfig.ini文件,并写入以下内容:
[mysql]
address=localhost
port=3306
username=root
password=root
2.建立对应的结构体
//这个里面的方法和成员变量一定要大写,否则访问不到
type MysqlConfig struct {
Address string `ini:"address"`
Port int `ini:"port"`
Username string `ini:"username"`
Password string `ini:"password"`
}
//如果有多个配置可以新建多个建构体
3.新建配置类的所有结构体(整合结构体)
type config struct {
//这个结构体的意义是:例如我们在找到配置文件的[mysql],就知道我应该给mysql的结构体赋值。而不是其他的结构体。通过`ini:"mysql"`能找到我要操作的结构体的名称是MysqlConfig
MysqlConfig `ini:"mysql"`
//这里是为了适应多个配置的情况。暂时就只写一个了
//RedisConfig `ini:"redis"`
}
4.加载配置类
//这里的data传的应该是&config ,是为了做到多配置的兼容。
func loadIni(fileName string, data interface{
}) (err error) {
t := reflect.TypeOf(data)
//判断是指针类型
if t.Kind() != reflect.Ptr {
err = fmt.Errorf("no ptr")
}
//判断必须是结构体指针
if t.Elem().Kind() !=reflect.Struct{
err = fmt.Errorf("no struct")
}
file, err := ioutil.ReadFile(fileName)
if err != nil {
return
}
//以行切割
split := strings.Split(string(file), "\r\n")
fmt.Println(split)
var structName string
for index, line := range split {
if len(line) == 0{
continue
}
//去掉空格
line = strings.TrimSpace(line)
//fmt.Println(data)
//如果是注释就跳过
if strings.HasPrefix(line,";") || strings.HasPrefix(line,"#"){
continue
}
//先找要操作的结构体
if strings.HasPrefix(line,"["){
//如果是[]这类的就是section
if line[0] !='[' || line[len(line)-1] != ']'{
fmt.Errorf("%d line error",index +1 )
return
}
sectioName := strings.TrimSpace(line[1:len(line)-1])
if len(sectioName) == 0{
fmt.Errorf("%d line error",index +1 )
return
}
//反射之后遍历config的成员变量,找到要操做的结构体
for i := 0; i < t.Elem().NumField(); i++ {
field := t.Elem().Field(i)
if sectioName == field.Tag.Get("ini"){
//找到了对应的字段名
structName = field.Name
fmt.Printf("找到了%s的结构体,%s\n",sectioName,structName)
break
}
}
}else {
//再找键值对
//如果是键值对,以等号分割去data里面取出结构体
//遍历嵌套结构体
if strings.Index(line,"=") == -1 || strings.HasPrefix(line,"=") {
err = fmt.Errorf("DATA:%s error" ,index +1)
}
index := strings.Index(line, "=")
key :=strings.TrimSpace(line[:index])
value :=strings.TrimSpace(line[index+1:])
v := reflect.ValueOf(data)
fmt.Printf("key ===%s\n",key)
fmt.Printf("value ===%s\n",value)
//拿到结构体Value值
sValue:= v.Elem().FieldByName(structName)
sType := sValue.Type()
if sType.Kind() != reflect.Struct{
fmt.Errorf("不是结构体")
}
var fileName string
var fileType reflect.StructField
//找到结构体的某个字段
for i := 0; i < sValue.NumField(); i++ {
filed := sType.Field(i)//tag是存储再类型信息中的
fileType = filed
if filed.Tag.Get("ini") == key {
fileName = filed.Name
fmt.Printf("fileName ===%s\n",fileName)
break
}
}
//错误字段,直接跳出。其实应该报错的。
if len(fileName)== 0{
continue
}
//通过key值找到了某个成员变量的名称,拿到这个成员变量的操作对象
fileObj := sValue.FieldByName(fileName)
//根据类型来赋值在配置文件中拿到的value
switch fileType.Type.Kind() {
//判断并赋值
case reflect.String:
fileObj.SetString(value)
case reflect.Int,reflect.Int8,reflect.Int16,reflect.Int32,reflect.Int64:
parseInt, err := strconv.ParseInt(value, 10, 64)
if err != nil {
err = fmt.Errorf("转换错误")
}
fileObj.SetInt(parseInt)
//这里还可以添加其他的类型。
}
}
}
return
}
5.测试。
func main() {
var mc config
//传入配置文件的位置。和config结构体的地址
err := loadIni("./ini/myconfig.ini", &mc)
if err != nil {
panic(err)
}
fmt.Println("看看反射后的结果:",mc.MysqlConfig)
}
//打印结果: 看看反射后的结果: {localhost 3306 root root}。完美!
总结:通过反射去一步步给需要的结构体的成员变量赋值。在这个过程中有以下几点要注意:
1.成员变量一定要大写开头。不然反射的时候设置值的时候会报错的!这点坑一定要避免。
2.读取配置文件本质是对字符串操作,在其中要多加判断,将不合格的数据直接抛出错误。更加符合现实。
3.逻辑上要清晰,读取过程是以[]为分割,再以键值对给某个结构体的成员变量赋值。声明变量存储某个字段的时候,例如[mysql]这个字段,要存储mysql这个字段,要声明一个是始终在for循环读取的代码的外面,因为下一次可能操作的是redis或其他的配置类。
边栏推荐
- ByteDance Flink Status Query Practice and Optimization
- 中移链EOSJS实战使用
- 马氏距离 (马哈拉诺比斯距离) (Mahalanobis distance)
- 概率论基础 - 6 - 切比雪夫不等式
- 概率论基础 - 14 - 指数分布
- 【Endnote】插入文献时,自动弹出select matching reference
- Software Testing Views on Test Platforms
- 概率论基础 - 1 - 基础概念
- Taurus.MVC WebAPI 入门开发教程3:路由类型和路由映射。
- 兆骑科创高层次人才引进平台,赛事活动举办,线上路演
猜你喜欢

The Hyper - V virtualization vmware data recovery 】 【 file is missing, virtualization server unavailable data recovery case

Postgresql源码(67)LWLock锁的内存结构与初始化

Use Redis source code to compile and release Redis For Windows distribution package for Windows

PaddleOCR User Guide

The memory problem is difficult to locate, that's because you don't use ASAN

It is more detailed than a certain teacher (anti-PPT series) series - custom type (below)

【CUDA学习笔记】什么是GPU计算

web安全入门-安全应急响应演练与报告

NLP 论文领读|无参数机器翻译遇上对比学习:效率和性能我全都要!

全栈软件测试工程师技术涨薪进阶路径图(附资料)
随机推荐
马氏距离 (马哈拉诺比斯距离) (Mahalanobis distance)
Tools to Improve Efficiency
恶访、黑产猖獗,做安全“守门人”| 创新场景50
'proxy' config is set properly, see "npm help config"
CRM巨头败走中国,Salesforce中国区或将解散?
Software Testing Views on Test Platforms
自媒体人必看的9个网站,每一个都很实用,值得收藏
业务局部多线程
01.Gameplay Architecture ECS简介
理财产品是只能看到本金看不到收益吗?
Business local multithreading
Taurus.MVC WebAPI Getting Started Development Tutorial 3: Route Types and Route Mapping.
DevEco Studio Configuration: Custom Header Code Comments
アィシャ / 艾夏
华为分析&联运活动,助您提升游戏总体付费
就是比某老师详细(反PPT系列)系列———自定义类型(下)
OpenHarmony Pixel Unit (eTS)
软件测试之对测试平台的看法
图神经网络 图像处理,为什么用图神经网络
概率论基础 - 13 - 泊松分布(Poisson分布)