mirror of
https://gitee.com/shikong-sk/golang-study
synced 2025-02-22 23:12:15 +08:00
docs: ini 文件解析
reflect 反射 解析 ini
This commit is contained in:
parent
ceea6dd095
commit
ce1b89f984
12
base/reflect/ini/conf.ini
Normal file
12
base/reflect/ini/conf.ini
Normal file
@ -0,0 +1,12 @@
|
||||
; mysql 数据库配置
|
||||
[mysql]
|
||||
host=127.0.0.1
|
||||
port=3306
|
||||
user=root
|
||||
password=12341234
|
||||
# redis 配置
|
||||
[redis]
|
||||
host= 127.0.0.1
|
||||
port = 6379
|
||||
password =12341234
|
||||
db=0
|
176
base/reflect/ini/main.go
Normal file
176
base/reflect/ini/main.go
Normal file
@ -0,0 +1,176 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IniConfig struct {
|
||||
Mysql MysqlConfig `ini:"mysql"`
|
||||
Redis RedisConfig `ini:"redis"`
|
||||
}
|
||||
|
||||
type MysqlConfig struct {
|
||||
Host string `ini:"host"`
|
||||
Port int `ini:"port"`
|
||||
User string `ini:"user"`
|
||||
Password string `ini:"password"`
|
||||
}
|
||||
|
||||
type RedisConfig struct {
|
||||
Host string `ini:"host"`
|
||||
Port int `ini:"port"`
|
||||
Password string `ini:"password"`
|
||||
Db int `ini:"db"`
|
||||
}
|
||||
|
||||
func loadIni(filePath string, v interface{}) (err error) {
|
||||
// 传入的 接收值 v 必须为指针类型 因为需要对齐进行赋值操作
|
||||
t := reflect.TypeOf(v)
|
||||
if v == nil || t.Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("接收者必须为指针类型\n")
|
||||
}
|
||||
|
||||
el := t.Elem()
|
||||
if el.Kind() != reflect.Struct {
|
||||
return fmt.Errorf("接收者必须为一个结构体对象\n")
|
||||
}
|
||||
|
||||
// 打开文件
|
||||
f, err := os.OpenFile(filePath, os.O_RDONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 读取整个文件
|
||||
b, _ := ioutil.ReadAll(f)
|
||||
// 释放文件占用
|
||||
_ = f.Close()
|
||||
|
||||
// ini 文件中
|
||||
// ; 开头的为注释
|
||||
// [xxx] 为节
|
||||
// key=value 为键值对
|
||||
|
||||
// 读取文件
|
||||
conf := string(b)
|
||||
// 替换换行符 \r\n 为 \n
|
||||
conf = strings.Replace(conf, "\r\n", "\n", -1)
|
||||
// 根据换行符 \n 分割行
|
||||
confSplit := strings.Split(conf, "\n")
|
||||
//fmt.Printf("%#v\n", confSplit)
|
||||
|
||||
var curSection string
|
||||
for _, line := range confSplit {
|
||||
// 去除 首尾 空格符
|
||||
trimReg, _ := regexp.Compile("\\s")
|
||||
line = trimReg.ReplaceAllLiteralString(line, "")
|
||||
|
||||
// 如果是以 ; 或 # 开头 的 视为注释 直接跳过
|
||||
annotationReg, _ := regexp.Compile("^[;|#]")
|
||||
if annotationReg.MatchString(line) {
|
||||
continue
|
||||
}
|
||||
|
||||
sectionReg, _ := regexp.Compile("^\\[(.*)]$")
|
||||
if sectionReg.MatchString(line) {
|
||||
sectionMatch := sectionReg.FindAllStringSubmatch(line, 1)
|
||||
if len(sectionMatch) < 1 {
|
||||
return fmt.Errorf("无效的 节 %s\n", line)
|
||||
}
|
||||
if len(sectionMatch[0]) < 2 {
|
||||
return fmt.Errorf("无效的 节 %s\n", line)
|
||||
}
|
||||
|
||||
section := sectionMatch[0][1]
|
||||
//fmt.Printf("节: %s\n", line)
|
||||
|
||||
value := reflect.ValueOf(v).Elem()
|
||||
for i := 0; i < el.NumField(); i++ {
|
||||
field := el.Field(i)
|
||||
if field.Tag.Get("ini") == section {
|
||||
item := value.FieldByName(field.Name)
|
||||
if item.Kind() == reflect.Ptr {
|
||||
return fmt.Errorf("接收者 %s 不能为指针\n", section)
|
||||
}
|
||||
//if item.Kind() == reflect.Struct {
|
||||
// fmt.Printf("%s 为结构体\n", section)
|
||||
//}
|
||||
|
||||
curSection = field.Name
|
||||
break
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.EqualFold(curSection, "") {
|
||||
continue
|
||||
}
|
||||
|
||||
keyValueReg, _ := regexp.Compile("^(.*)=(.*)$")
|
||||
if keyValueReg.MatchString(line) {
|
||||
keyValueMatch := keyValueReg.FindAllStringSubmatch(line, -1)
|
||||
if len(keyValueMatch) < 1 {
|
||||
//fmt.Println("未找到 匹配的 键值对")
|
||||
continue
|
||||
}
|
||||
keyValueSubMatch := keyValueMatch[0]
|
||||
if len(keyValueSubMatch) < 3 {
|
||||
//fmt.Println("未找到 匹配的 键值对")
|
||||
continue
|
||||
}
|
||||
k := keyValueSubMatch[1]
|
||||
val := keyValueSubMatch[2]
|
||||
//fmt.Printf("键值对: k: %#v => v: %#v\n", k, val)
|
||||
|
||||
sectionReflectType, _ := reflect.TypeOf(v).Elem().FieldByName(curSection)
|
||||
sectionType := sectionReflectType.Type
|
||||
sectionVal := reflect.ValueOf(v).Elem().FieldByName(curSection)
|
||||
|
||||
if sectionVal.Kind() != reflect.Struct {
|
||||
return fmt.Errorf("section 接收者 需为 struct 类型\n")
|
||||
}
|
||||
|
||||
for i := 0; i < sectionVal.NumField(); i++ {
|
||||
selectionKey := sectionType.Field(i).Tag.Get("ini")
|
||||
|
||||
if strings.EqualFold(selectionKey, k) {
|
||||
//fmt.Println(selectionKey, sectionVal.Field(i).Kind())
|
||||
switch sectionVal.Field(i).Kind() {
|
||||
case reflect.Int:
|
||||
intVal, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sectionVal.Field(i).SetInt(int64(intVal))
|
||||
case reflect.String:
|
||||
sectionVal.Field(i).SetString(val)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Println(line)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
config := new(IniConfig)
|
||||
err := loadIni("./base/reflect/ini/conf.ini", config)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%#v\n", config)
|
||||
}
|
Loading…
Reference in New Issue
Block a user