course/ini_unmarshal/conf_ini.go

103 lines
2.5 KiB
Go
Raw Normal View History

2024-07-02 18:19:18 +08:00
package main
import (
"fmt"
"os"
"strings"
"reflect"
)
//定义结构体
type MysqlConfig struct {
Address string `ini:"address"`
Port int `ini:"port"`
Username string `ini:"username"`
Password string `ini:"password"`
}
type RedisConfig struct {
host string `ini:"host"`
Port int `ini:"port"`
Password string `ini:"password"`
Database string `ini:"database"`
}
type Config struct {
RedisConfig `ini:"mysql"`
MysqlConfig `ini:"redis"`
}
func Loadini(fileName string, data interface{}) (err error) {
//0.参数的校验,对函数中修改值,必须是结构体指针
t := reflect.TypeOf(data)
//v := reflect.ValueOf(data)
//校验指针类型
if t.Kind() != reflect.Ptr {
err = fmt.Errorf("data should be pointer")
return
}
//校验结构体类型由于是指针要用elem方法
if t.Elem().Kind() != reflect.Struct {
err = fmt.Errorf("data should be struct")
return
}
//1.读取文件
b, err := os.ReadFile(fileName) //读取文件拿到字节类型的数据
if err != nil {
return
}
lineSlice := strings.Split(string(b), "\r\n") //字节类型的数据按照换行符切分
fmt.Printf("%#v\n", lineSlice)
//var structName string
//2.一行一行的读取数据
for idx, line := range lineSlice {
//2.1如果是注释,就跳过
line = strings.TrimSpace(line)
if strings.HasPrefix(line, ";") || strings.HasPrefix(line, "#") {
continue
}
//2.2如果是[开头的就表示节section
if strings.HasPrefix(line, "[") {
//校验1 首尾的[]都需要存在
if line[0] != '[' || line[len(line)-1] != ']' {
err = fmt.Errorf("line:%d syntax error", idx+1)
return
}
//结之间能取到的内容比如redis或者mysql这个字符串
sectionName := strings.TrimSpace(line[1 : len(line)-1])
//校验2 []之间应该有内容
if len(sectionName) == 0 { //切片:左包含右不包含
err = fmt.Errorf("line:%d syntax error", idx+1)
return
}
//根据字符串sectionName到data中根据反射找到结构体
for i := 0; i < t.Elem().NumField(); i++ {
field := t.Elem().Field(i)
if field.Tag.Get("ini") == sectionName {
//找到对应的嵌套结构体
//structName = field.Name
break
}
}
} else {
//2.3如果不是[,就是=分割的键值对
}
}
return //
}
func main() {
var cfg Config
err := Loadini("./ini_unmarshal/config.ini", &cfg)
if err != nil {
fmt.Println("load ini error:", err)
return
}
fmt.Println(cfg)
}