# Golang 利用反射实现读取配置文件 **Published by:** [Robin](https://paragraph.com/@robin-8/) **Published on:** 2023-03-02 **URL:** https://paragraph.com/@robin-8/golang-6 ## Content package main import ( "errors" "fmt" "io/ioutil" "reflect" "strings" ) type MysqlConf struct { Address string `ini:"address"` Port string `ini:"port"` Username string `ini:"username"` Password string `ini:"password"` } type Redisconf struct { Host string `ini:"host"` Port string `ini:"port"` Password string `ini:"password"` Database string `ini:"database"` } type Conf struct { MysqlConf `ini:"mysql"` Redisconf `ini:"redis"` } func loadIni(fileName string, data interface{}) (err error) { t := reflect.TypeOf(data) v := reflect.ValueOf(data) //1 判断传进来指针 并且是结构体指针 if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct { err = errors.New("input type is not Struct Ptr") return } //2. 读文件得到字节数据类型 content, err := ioutil.ReadFile(fileName) if err != nil { err = errors.New("open file faild") return } //3. 一行一行读数据 var sectionName string var structName string lines := strings.Split(string(content), "\n") for _, line := range lines { line = strings.TrimSpace(line) //3.1 空行跳过循环 if len(line) == 0 { continue } //3.2 注释跳过循环 if strings.HasPrefix(line, "#") { continue } //3.3 如果是 [ 开头就表示是section字段 if strings.HasPrefix(line, "[") { sectionName = strings.TrimSpace(line[1 : len(line)-1]) for i := 0; i < v.Elem().NumField(); i++ { field := v.Elem().Type().Field(i) if sectionName == field.Tag.Get("ini") { structName = field.Name } } } else { // 获取seciton下面的key and value key := strings.TrimSpace(strings.Split(line, "=")[0]) value := strings.TrimSpace(strings.Split(line, "=")[1]) // 获取嵌套里的struct structObj := v.Elem().FieldByName(structName) // 获取最终的字段 var fieldName string for i := 0; i < structObj.NumField(); i++ { field := structObj.Type().Field(i) if key == field.Tag.Get("ini") { fieldName = field.Name } } //赋值操作 structObj.FieldByName(fieldName).SetString(value) } } return nil } func main() { var cfg Conf err := loadIni("./conf.ini", &cfg) if err != nil { fmt.Println(err) return } fmt.Printf("Mysql address is:%s\n", cfg.MysqlConf.Address) fmt.Printf("Mysql port is:%s\n", cfg.MysqlConf.Port) fmt.Printf("Mysql username is:%s\n", cfg.MysqlConf.Username) fmt.Printf("Mysql password is:%s\n", cfg.MysqlConf.Password) fmt.Printf("Redis host is:%s\n", cfg.Redisconf.Host) fmt.Printf("Redis port is:%s\n", cfg.Redisconf.Port) fmt.Printf("Redis password is:%s\n", cfg.Redisconf.Password) fmt.Printf("Redis database is:%s\n", cfg.Redisconf.Database) } conf.ini [mysql] address=192.168.100.100 port=3306 username=root password=BaVzJJJlNBS47uo9KduonCtMrdPhyYVG [redis] host= 127.0.0.1 port= 6379 password=123.com database=0 ## Publication Information - [Robin](https://paragraph.com/@robin-8/): Publication homepage - [All Posts](https://paragraph.com/@robin-8/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@robin-8): Subscribe to updates