mirror of
https://gitee.com/shikong-sk/golang-study
synced 2025-02-23 15:32: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