zoukankan      html  css  js  c++  java
  • golang-reflect实战ini配置文件

    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))
    }
    
  • 相关阅读:
    vue 子组件像父组件传递数据
    SQL Query XML column.   SQL 查询 xml 字段
    最方便的批处理延时方法
    Automation testing framework for RFT execution with STAF+STAX . [Session1]
    Disable Windows server 2003 Security Warning.
    Perl初级教程 (5) 遍历文件夹内指定扩展名文件,查找匹配关键字的输出。
    Perl 基于 Windows 环境 搭建
    Perl Scalar
    Package you execution files with Iexpress.exe
    SQLServer2005 remove log file.
  • 原文地址:https://www.cnblogs.com/egrep/p/15272051.html
Copyright © 2011-2022 走看看