直接上代码:

  1 package main
2
3 import (
4 "fmt"
5 "io/ioutil"
6 "reflect"
7 "strconv"
8 "strings"
9 )
10
11 type MysqlConfig struct {
12 Address string `ini:"address"`
13 Port int `ini:"port"`
14 UserName string `ini:"username"`
15 PassWord string `ini:"password"`
16 }
17
18 type RedisConfig struct {
19 Host string `ini:"host"`
20 Port int `ini:"port"`
21 PassWord string `ini:"password"`
22 DataBase int `ini:"database"`
23 }
24
25 type Config struct {
26 MysqlConfig `ini:"mysql"`
27 RedisConfig `ini:"redis"`
28 }
29
30 func loadIni(fileName string, v interface{}) error {
31 // 参数校验:v需为结构体指针类型
32 t := reflect.TypeOf(v)
33 if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct {
34 return fmt.Errorf("v should be a struct ptr")
35 }
36
37 // 读取文件得到数据后立即关闭文件
38 f, err := ioutil.ReadFile(fileName)
39 if err != nil {
40 return err
41 }
42 // 逐行获取文件内容,将值赋值给对应的结构体对象
43 lineSlice := strings.Split(string(f), "\n")
44 var structName string
45 for index, line := range lineSlice {
46 line = strings.TrimSpace(line)
47 // 跳过注释和空行
48 if strings.HasPrefix(line, ";") || strings.HasPrefix(line, "#") || len(line) == 0 {
49 continue
50 }
51 // 以 [ 开头,为节点,需以 ] 结尾,且除空格外存在字符
52 if strings.HasPrefix(line, "[") {
53 if line[len(line) - 1] != ']' {
54 return fmt.Errorf("line:%d syntax error", index+1)
55 }
56 sectionName := strings.TrimSpace(line[1:len(line)-1])
57 if len(sectionName) == 0 {
58 return fmt.Errorf("line:%d syntax error", index+1)
59 }
60 // 根据字符串sectionName去v里面根据反射找到对应的结构体
61 for i :=0 ; i < t.Elem().NumField(); i ++ {
62 field := t.Elem().Field(i)
63 if sectionName == field.Tag.Get("ini") {
64 structName = field.Name
65 //fmt.Println(structName)
66 break
67 }
68 }
69 } else {
70 // 不以 [ 开头,为以=分割的键值对
71 if strings.Index(line, "=") == -1 || strings.HasPrefix(line, "=") {
72 return fmt.Errorf("line:%d syntax error", index+1)
73 }
74 // 根据struct名称找到对应结构体
75 data := reflect.ValueOf(v)
76 structValue := data.Elem().FieldByName(structName) // 拿到嵌套结构体的值信息
77 structType := structValue.Type() // 拿到嵌套结构体的类型信息
78 if structType.Kind() != reflect.Struct {
79 return fmt.Errorf("config struct field %s must be a struct", structName)
80 }
81 // 拆分键值对并赋值
82 paramSlice := strings.Split(line, "=")
83 key, value := strings.TrimSpace(paramSlice[0]), strings.TrimSpace(paramSlice[1])
84 for x := 0; x < structType.NumField(); x ++ {
85 // 先拿到fieldType,fieldType中可以拿到field的值类型
86 fieldType := structType.Field(x)
87 if fieldType.Tag.Get("ini") == key {
88 // 根据field名称拿到field字段
89 fieldV := structValue.FieldByName(fieldType.Name)
90 // 给字段赋值
91 switch fieldType.Type.Kind() {
92 case reflect.String:
93 fieldV.SetString(value)
94 case reflect.Int,reflect.Int8,reflect.Int16,reflect.Int32,reflect.Int64:
95 valueInt, err := strconv.ParseInt(value, 10, 64)
96 if err != nil {
97 return fmt.Errorf("parseInt error, err:%v", err)
98 }
99 fieldV.SetInt(valueInt)
100 case reflect.Float32:
101 valueFloat, err := strconv.ParseFloat(value, 32)
102 if err != nil {
103 return fmt.Errorf("parseFloat error, err:%v", err)
104 }
105 fieldV.SetFloat(valueFloat)
106 case reflect.Float64:
107 valueFloat, err := strconv.ParseFloat(value, 64)
108 if err != nil {
109 return fmt.Errorf("parseFloat error, err:%v", err)
110 }
111 fieldV.SetFloat(valueFloat)
112 case reflect.Bool:
113 valueBool, err := strconv.ParseBool(value)
114 if err != nil {
115 return fmt.Errorf("parseBool error, err:%v", err)
116 }
117 fieldV.SetBool(valueBool)
118 }
119 break
120 }
121 }
122 }
123 }
124 return nil
125 }
126
127 func main() {
128 var config Config
129 fileName := "/home/xxx/data/demo_config/config.ini"
130 err := loadIni(fileName, &config)
131 if err != nil {
132 fmt.Printf("load ini failed, err:%v", err)
133 }
134 fmt.Println("mysql config:")
135 fmt.Printf("address:%s\tport:%d\tusername:%s\tpassword:%s\n", config.MysqlConfig.Address, config.MysqlConfig.Port, config.MysqlConfig.UserName, config.MysqlConfig.PassWord)
136
137 fmt.Println("redis config:")
138 fmt.Printf("host:%s\tport:%d\tpassword:%s\tdatabase:%d\n", config.RedisConfig.Host, config.RedisConfig.Port, config.RedisConfig.PassWord, config.RedisConfig.DataBase)
139 }

最新文章

  1. 带你实现开发者头条APP(四)---首页优化(加入design包)
  2. LeetCode 104. Maximum Depth of Binary Tree
  3. Intellij_idea-14官方快捷键中文版
  4. 在myeclipse文件中如何创建properties类型的文件,从而连接数据库
  5. ANSI
  6. 百度地图 获取矩形point
  7. Unity3d Physically Based Hair Shading in Unreal
  8. Universal Naming Convention (UNC)
  9. 【原创】Linux 增加系统调用
  10. C# DataTable怎么合计字段
  11. 搭建带热更新功能的本地开发node server
  12. SAC E#1 - 一道神题 Sequence1
  13. JAVA之旅(一)——基本常识,JAVA概念,开发工具,关键字/标识符,变量/常量,进制/进制转换,运算符,三元运算
  14. JavaScript中的获取元素的方法
  15. Tip:HttpServletRequest
  16. 洛谷3825 [NOI2017]游戏 2-sat
  17. 【CSS】元素样式
  18. 工控安全入门之Modbus(转载)
  19. C++:实现类似MFC的IsKindOf功能
  20. PCL滤波介绍(3)

热门文章

  1. BUG日记之——MP使用EeasyExcel技术,读取Excel并保存到数据库中出错
  2. rust 网上资料记录(自用)
  3. 详解Redisson分布式限流的实现原理
  4. Util类 为了代码复用将一些连接数据库的代码
  5. C++练习8 常量的说明
  6. Connect-The-Dots
  7. Mbps 与 MBps
  8. Java对象布局
  9. Python Socket 基础多用户编程
  10. 问题集锦 ~ MySQL