Go利用反射实现一个ini文件的解析器程序

news2024/10/6 0:33:23
package main

import (
	"bufio"  // 逐行读取配置文件
	"fmt"
	"log"
	"os"
	"reflect"
	"strconv"
	"strings"
)

type Config struct {	// 定义配置结构体
	Section1 Section1 `ini:"section1"`	// 嵌套结构体1
	Section2 Section2 `ini:"section2"`	// 嵌套结构体2
}

type Section1 struct {
	Key1 string `ini:"key1"`
	Key2 int    `ini:"key2"`
}

type Section2 struct {
	Key3 float64 `ini:"key3"`
	Key4 bool    `ini:"key4"`
}

// fieldName 函数返回一个匹配函数,用于在结构体中查找字段名与给定字段名相同的字段
func fieldName(fieldName string) func(string) bool {
	return func(tag string) bool {
		return strings.EqualFold(tag, fieldName)	// 调用strings.EqualFold 函数进行不区分大小写匹配
	}
}

func main() {
	file, err := os.Open("config.ini")
	if err != nil {
		log.Fatalf("Failed to open file: %v", err)
	}
	defer file.Close()

	cfg := Config{}
	scanner := bufio.NewScanner(file)
	currentSection := ""
	v := reflect.ValueOf(&cfg).Elem()

	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())

		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}

		if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
			currentSection = strings.Trim(line, "[]")
			sectionField := v.FieldByNameFunc(fieldName(currentSection))
			if !sectionField.IsValid() {
				log.Printf("Invalid section: %s", currentSection)
			}
		} else {
			parts := strings.SplitN(line, "=", 2)
			if len(parts) != 2 {
				log.Printf("Invalid key-value pair: %s", line)
				continue
			}

			key := strings.TrimSpace(parts[0])
			value := strings.TrimSpace(parts[1])

			if currentSection == "" {
				log.Printf("Key-value pair found outside of any section: %s", line)
				continue
			}

			sectionField := v.FieldByNameFunc(fieldName(currentSection))
			if !sectionField.IsValid() {
				log.Printf("Invalid section: %s", currentSection)
				continue
			}

			field := sectionField.FieldByNameFunc(fieldName(key))
			if !field.IsValid() {
				log.Printf("Invalid key: %s", key)
				continue
			}

			switch field.Kind() {
			case reflect.String:
				field.SetString(value)
			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
				intValue, err := strconv.ParseInt(value, 10, 64)
				if err != nil {
					log.Printf("Failed to parse int value for key %s: %v", key, err)
					continue
				}
				field.SetInt(intValue)
			case reflect.Float32, reflect.Float64:
				floatValue, err := strconv.ParseFloat(value, 64)
				if err != nil {
					log.Printf("Failed to parse float value for key %s: %v", key, err)
					continue
				}
				field.SetFloat(floatValue)
			case reflect.Bool:
				boolValue, err := strconv.ParseBool(value)
				if err != nil {
					log.Printf("Failed to parse bool value for key %s: %v", key, err)
					continue
				}
				field.SetBool(boolValue)
			default:
				log.Printf("Unsupported field type for key %s", key)
			}
		}
	}

	if err := scanner.Err(); err != nil {
		log.Fatalf("Error while scanning file: %v", err)
	}

	fmt.Printf("%+v\n", cfg)
}
[Section1]
key1 = value1
key2 = 100

[Section2]
key3 = 3.14
key4 = true

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1204998.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

洗地机哪个牌子最好用?洗地机怎么选?2023洗地机选购推荐

家里有小孩或者是养有宠物的都有一个深刻的体验,那就是房子每天都很乱,隔三岔五就得做一次卫生清理、地板杀菌等。如果是房屋面积太大的话,只靠自己手动清洁是非常的耗时间并且还很劳累。洗地机的出现可谓是造福人类,解脱了家庭劳…

EM@一次双绝对值不等式

文章目录 一次双绝对值不等式求解步骤去绝对值情况分析👺例例代数法几何方法比较 例 一次双绝对值不等式求解步骤 设 f ∣ f 1 ∣ ∣ f 2 ∣ f|f_1||f_2| f∣f1​∣∣f2​∣, f 1 , f 2 f_1,f_2 f1​,f2​都是一次多项式,则原不等式 f ⩾ a f\geqslant{a} f⩾a或 …

跨越编程界限:C++到JavaSE的平滑过渡

JDK安装 安装JDK 配置环境变量: Path 内添加 C:\Program Files\Java\jdk1.8.0_201\bin 添加 JAVA_HOME C:\Program Files\Java\jdk1.8.0_201 添加 CLASSPATH .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar 第一个Java程序 HelloWorld.java public class…

记录--让我们来深入了解一下前端“三清”是什么

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前端“三清” 在前端开发中,我们经常听到关于“三清”的说法,即 window、document、Object。这三者分别代表了 BOM(浏览器对象模型)、DOM(文档对象模型)以及 JS 的顶层对象。在…

Git精讲(一)

📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、Git初识1、提出问题2、如何解决--版本控制器3、注意事项 二、Git 安装1、Linux-centos2、…

世微 升压恒压IC dc-dc转换器 充电器手持设备便携式产品 AP8660

AP8660是一款升压dc-dc转换器,内置MOS调节器,内部补偿,还可以最小6个外部组件,内部的软识启动功能可以降压涌入电流 AP8660 SOT23-6封装,可以为PCB提供节省空间 特点 可调输出,最高达到24W 内部固定PWM频…

语言大模型的预训练过程——从无尽数据到海量知识

从目前研究结果看,Transformer是足够强大的特征抽取器,通过预训练过程,Transformer学到了什么?知识是如何存取的?我们又如何修正错误知识?本文讲述这方面的研究进展。 1、求知:LLM学到了什么知…

【JAVA】去掉 if...else 的七种绝佳之法...

文章目录 前言方法一:提前 return方法二:枚举方案三:Optional 判空方案四:表驱动法方案五:策略模式 工厂方法方案六:责任链模式方案七:Function总结 前言 我相信小伙伴一定看过多篇怎么去掉 i…

解决渗透测试js文件泄露

解决办法:使用过滤器过滤 public class StaticSourceFilter implements Filter {private static Logger logger LoggerFactory.getLogger(StaticSourceFilter.class);Overridepublic void init(FilterConfig filterConfig) throws ServletException {}Overridepub…

http-server安装使用

前段时间给电脑重装了系统,很多东西都没了,今天想在浏览器打开一个本地的html文件,发现电脑上没有http-server,于是装了一个,并且记录下安装过程 1、安装 nodejs,但如果你电脑上有,就无需下载 …

html5 初步了解

1、html5 含义 简而言之,html5 其实就是新的一代html标准! 2、html5的优缺点 优点 语义化html 增加了很多语义化的标签,让html结构更加清晰,更具可读性由于增加了很多语义化的标签,对SEO更加友好 缺点 其他主流浏…

day59【单调栈】503.下一个更大元素Ⅱ 42.接雨水

文章目录 503.下一个更大元素Ⅱ42.接雨水 503.下一个更大元素Ⅱ 力扣题目链接 代码随想录讲解链接 题意:给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。 数…

(只需三步)虚拟机上vm的ubuntu不能联上网怎么办

第一步:重启虚拟网络适配器 第二步:删掉网络适配器,重新添加 第三步:重启虚拟机网络服务器 sudo service network-manager stop sudo rm /var/lib/NetworkManager/NetworkManager.state sudo service network-manager start 再打…

【机器学习基础】机器学习入门(2)

🚀个人主页:为梦而生~ 关注我一起学习吧! 💡专栏:机器学习 欢迎订阅!后面的内容会越来越有意思~ 💡往期推荐:【机器学习基础】机器学习入门(1) 💡…

【算法|动态规划 | 区间dp No.1】AcWing 282. 石子合并

个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【AcWing算法提高学习专栏】【手撕算法系列专栏】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程&a…

数据结构--图解单链表

学习链表最重要的就是会画图,尤其是要理解链表的逻辑结构和物理结构,理解链表的底层原理才能使用的如鱼得水。 希望这篇文章可以帮助各位,记得关注收藏哦;若发现问题希望私信博主,十分感谢。 当然学习链表是需要大家对…

【PWN · heap | unlink | free_hook】[SUCTF 2018 招新赛]unlink

在前期学习了unlink后,今天翻NSSCTF找到一道名为unlink的题目,尝试不看wp做。过程很顺利! 前言 题目对于知识点unlink还是非常裸的,很直接,思路很清晰。 一、题目 二、思路浅析 通过对该程序的反编译,我们…

AGV与AMR的区别

如今,市面上最受关注的两类工业移动机器人分别是AGV和AMR。但大众对于两者的区别还是不甚了解,因此小编将通过这篇文章为大家详细解释。 一、概念阐述 【AGV 】 AGV (Automated Guided Vehicle) 即自动导引运输车,可指基于各种定位导航技术…

第二章:main 方法

系列文章目录 文章目录 系列文章目录前言一、main 方法总结 前言 main方法详解。 一、main 方法 //main方法的形式 public static void main(String[] args){}解释main方法main方法被虚拟机调用Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是publi…

C++类中的const使用

目录 一,const成员函数 1,const成员函数的语法 2,相同限定符之间的调用 3,不同限定符对象与函数的调用 4,不同限定符函数之间的调用 一,const成员函数 1,const成员函数的语法 将const修饰…