config.ini 配置文件
#this is comment
;this a comment
;[]表示一个section
[server]
ip = 192.168.0.1
port = 9000
[mysql]
username = root
passwd = admin
database = test
host = 192.168.10.10
port = 8000
timeout = 1.2
package main
import (
"fmt"
"io/ioutil"
"reflect"
"strconv"
"strings"
)
/*
需求就是读取config.ini 配置文件
反序列化对config 这个结构体中
*/
type ServerConf struct {
Ip string `ini:"ip"`
Port int `ini:"port"`
}
type MysqlConf struct {
Username string `ini:"username"`
Passwd string `ini:"passwd"`
Database string `ini:"database"`
Host string `ini:"host"`
Port int `ini:"port"`
Timeout float64 `ini:"timeout"`
}
type Config struct {
Server ServerConf `ini:"server"`
Mysql MysqlConf `ini:"mysql"`
}
func Unmarshal(data []byte, v interface{}) (err error) {
//严谨判断
rt := reflect.TypeOf(v)
kind := rt.Kind()
//判断是不是指针
if kind != reflect.Ptr {
panic("类型错误必须传入指针")
return err
}
//判断是不是结构体
if rt.Elem().Kind() != reflect.Struct{
panic("类型错误必须是结构体指针")
return err
}
//data就是我们读取的配置数据
//按照每一行切割读取
datastrsplit := strings.Split(string(data), "
")
//大标签Tag的名称
var LableTagName string
//大标签Filed 的名称
var LableFieldName string
for _,line := range datastrsplit{
//去除两边空格
line =strings.TrimSpace(line)
//判断这行数据是不是为空 或者是注释
if len(line) == 0 || line[0] == '#' || line[0] == ';' {
continue
}
//fmt.Printf("line:%q
",line)
//如果他是以 [ 开始 结尾] 说明他是一个大标签 server mysql
//fmt.Printf("line HasPrefix:%v
",strings.HasPrefix(line,"["))
//fmt.Printf("line HasSuffix:%v
",strings.HasSuffix(line,"]"))
if strings.HasPrefix(line,"[") && strings.HasSuffix(line,"]") {
LableTagName = line[1:strings.Index(line,"]")]
//fmt.Printf("LableTagName:%v
",LableTagName)
//查找打标签 并且返回 大标签对应tag 结构体字段的名称 比如 server tag 对应结构体字段Server
//最后需要通过结构体字段进行查找字段进行赋值
LableFieldName = BigLablesFieldName(LableTagName, rt)
//fmt.Printf("BigLablesFieldName LableFieldName:%v
",LableFieldName)
continue
}
//找出来key value 进行设置
RefelectSetStruct(LableFieldName,line,v)
}
return
}
//查找打标签在反射结构体中的标签tag
func BigLablesFieldName(LableTagName string,rt reflect.Type) (LableFieldName string){
//查找结构体中的字段
//var LableFieldName string
for i:=0;i<rt.Elem().NumField();i++{
field := rt.Elem().Field(i)
TagName := field.Tag.Get("ini")
if LableTagName == TagName {
LableFieldName=field.Name
return
}
}
return
}
//根据key value 进行设置到结构体
func RefelectSetStruct(LableFieldName string ,line string,v interface{}){
//获取key 和 value 数据
lines := strings.Split(line,"=")
key := strings.TrimSpace(lines[0])
value := strings.TrimSpace(lines[1])
//fmt.Printf("key:%q value:%q
",key,value)
rf := reflect.TypeOf(v)
filed, _ := rf.Elem().FieldByName(LableFieldName)
rf = filed.Type
//找出对应LableFieldName 对英的字段
//进行比较 key 是不是 等于tagName
var KeyFieldName string
for i:=0;i< rf.NumField();i++{
field := rf.Field(i)
filedTagName := field.Tag.Get("ini")
if key == filedTagName {
KeyFieldName = field.Name
continue
}
}
//进行设置
rv := reflect.ValueOf(v)
rv = rv.Elem().FieldByName(LableFieldName)
//fmt.Printf("Lablesvalues:%v
",rv)
filedvalues := rv.FieldByName(KeyFieldName)
//fmt.Printf("filedvalues:%v
",filedvalues)
switch filedvalues.Kind() {
case reflect.String:
filedvalues.SetString(value)
case reflect.Int:
intvalue,_ := strconv.Atoi(value)
filedvalues.SetInt(int64(intvalue))
case reflect.Float64:
valuefloat, _ := strconv.ParseFloat(value, 64)
filedvalues.SetFloat(valuefloat)
default:
}
}
func Marshal(v interface{}) ([]byte, error) {
//判断是不是结构体
rt := reflect.TypeOf(v)
//LableName := rt.Name()
//fmt.Printf("[%v]
",LableName)
//fmt.Printf("rt:%#v
",rt)
rv := reflect.ValueOf(v)
//fmt.Printf("rv%#v
",rv)
var results []byte
var err error
kind := rt.Kind()
if kind != reflect.Struct{
panic("必须是一个结构体")
}
for i:=0;i<rt.NumField();i++{
fieldLable := rt.Field(i)
//判断是不是普通的类似 如果是结构体需要重新进行解析
//fmt.Printf("~~~~ fieldLable:%v
",fieldLable)
fieldLablevalue := rv.FieldByName(fieldLable.Name)
kind := fieldLable.Type.Kind()
if kind == reflect.Struct{
//fmt.Printf("kind:%v
",kind)
Labname := fmt.Sprintf("[%v]
",fieldLable.Name)
//fmt.Printf("[%v]
",fieldLable.Name)
results=append(results,[]byte(Labname)...)
for i:=0;i< fieldLable.Type.NumField();i++{
field := fieldLable.Type.Field(i)
fieldvalue:=fieldLablevalue.FieldByName(field.Name)
fmt.Printf("key:%v = value:%v
",field.Tag.Get("ini"),fieldvalue)
results=append(results,[]byte(field.Tag.Get("ini")+" = ")...)
switch fieldvalue.Kind() {
case reflect.Int:
value:=fieldvalue.Int()
valurstr := fmt.Sprintf("%v
",value)
results=append(results,[]byte(valurstr)...)
case reflect.Float64:
value:=fieldvalue.Float()
valurstr := fmt.Sprintf("%v
",value)
results=append(results,[]byte(valurstr)...)
case reflect.String:
results=append(results,[]byte(fieldvalue.String()+"
")...)
}
}
}
}
return results,err
}
func main(){
data, err := ioutil.ReadFile("./config.ini")
if err != nil {
fmt.Println(err)
return
}
var config Config
fmt.Println("Unmarshal ini")
err = Unmarshal(data,&config)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("config:%#v
",config)
fmt.Println()
fmt.Println("Marshal ini")
marshal, err := Marshal(config)
fmt.Printf("%v
",string(marshal))
}