[golang]自己动手实现ini文件读取

本文介绍了一个使用Go语言实现的Ini配置文件解析器。通过定义接口和具体结构体,该解析器能处理Ini文件的基本元素,包括注释、模块和配置项,并提供了GetString方法来获取配置值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近迷恋go语言,但我是个编程菜鸟,这个读取参考了beego的config,只是半成品,不过能够正常运行。

  1. 接口的设计
type Parser interface {
	Parse() error
}

type Config interface {
	GetString(string)string
	Parser
}

目前只支持最小操作,解析和获取。在读取之前,要让config实例化一个对象:

var config Config

func RegisterConfig(mode,path string){
	switch mode{
	case "ini":
		config=ini.NewIniConfig(path)
	case "json":
	case "xml":
	default:
		panic("Dosn't Supported configure type.")
	}
}

这样,只要Iniconfig实现了config接口,就能将实例化的对象赋值给config,这个对象是全局的,外部调用config.Regi...之后,调用封装好的操做即可获取实例,实现功能。

全局实现:util.go

package config

import "mytools/config/ini"

type Parser interface {
	Parse() error
}

type Config interface {
	GetString(string)string
	Parser
}

var config Config

func RegisterConfig(mode,path string){
	switch mode{
	case "ini":
		config=ini.NewIniConfig(path)
	case "json":
	case "xml":
	default:
		panic("Dosn't Supported configure type.")
	}
}

func GetConfig()*Config{
	return &config
}

IniConfig实现

package ini

import (
	"os"
	"sync"
	"bufio"
	"io"
	"bytes"
	"strings"
	"log"
)

var(
	DEFAULT_SECTION string
	COMMENT []byte
	SEPARATOR []byte
	//SECTION_START string
	//SECTION_END string
)

//const(
//	LEFT = iota
//	RIGHT
//)

func init(){
	DEFAULT_SECTION="default"
	COMMENT=[]byte{'#'}
	SEPARATOR=[]byte{'='}
}

//type EntryConfig struct {
//	IsAlign bool //对齐
//	AlignType int //对齐类型
//}

type IniEntry struct {
	value interface {}
}


type IniConfig struct {
	filename string
	section map[string]*IniSection
	sync.RWMutex
}

func NewIniConfig(path string) *IniConfig{
	config:=&IniConfig{path,make(map[string]*IniSection),sync.RWMutex{}}
	config.section[DEFAULT_SECTION]=NewIniSection()
	return config
}


func (c *IniConfig)Parse() error{
	file,err:=os.Open(c.filename)
	if err!=nil {
		return err
	}
	c.Lock()
	defer c.Unlock()
	defer file.Close()

	buf:=bufio.NewReader(file)
	section:=DEFAULT_SECTION
	var bufRead int
	for{
		//读取一行缓存
		line,_,err:=buf.ReadLine()
		bufRead = bufRead + len(line)
		if err==io.EOF{
			//读到文件结尾,退出循环
			break
		}
		if bytes.Equal(line,[]byte("")){
			//空行直接跳过循环
			continue
		}
		//删除行两端的空白字符
		line=bytes.TrimSpace(line)
		if bytes.HasPrefix(line,COMMENT){
			//注释行暂时不做处理
			continue
		}
		if bytes.HasPrefix(line,[]byte("["))&&bytes.HasSuffix(line,[]byte("]")){
			//section处理
			//现在line确定为"[sectioname]"
			//不知道有没有合法性检查
			section=string(line[1:len(line)-1])
			section=strings.ToLower(section)
			if _,ok:=c.section[section];!ok{
				c.section[section]=NewIniSection()
			}
		}else{
			//key=value处理
			pair:= bytes.SplitN(line,SEPARATOR,2)
			key:= pair[0]
			val:=pair[1]
			if _,ok:=c.section[section];!ok{
				c.section[section]=NewIniSection()
			}
			log.Println(key,val)
			c.section[section].addEntry(string(key),string(val))
		}
	}
	return nil
}

func (c *IniConfig)RemoveSection(key string) error{
	return nil
}

func (c *IniConfig)GetString(k string) string{
	s:=strings.Split(k,":")
	var sec string
	var key string
	if len(s)==1{
		sec=DEFAULT_SECTION
		key=s[0]
		log.Println(sec,key)
	}else{
		sec=s[0]
		key=s[1]
		log.Println(sec,key)
	}
	if v,ok:=c.section[sec].getEntry(key).(string);ok{
		return v
	}
	return ""
}
首先看结构,Ini文件最基本的组成由注释,模块,项三个部分,其中,注释行可能由特定的字符开头,比如“#”,“;”等,现在默认是"#",如果要支持自定义字符,添加接口和check操作就能实现。在模块加载时我们就已经定义好了默认操作。参见init函数。
在回过头看看section,iniconfig是一个深度为2的树结构,每个树的跟节点是sectionname,子节点是配置项key=value,默认有一个defaultsection。
在解析方面,逐行读取,然后根据ini文件特点,处理注释行,注释段(未实现),section,和项,之后把他们转换成数据结构保存在Iniconfig中,只要调用GetString即可拿到配置项,语法为"section:key"。
那么,先到这里吧。

菜鸟轻喷。。。。。




                
<think>好的,用户之前问过JWT和HTTP Auth的比较,现在又转向了GolangINI配置文件解析。这可能意味着他们正在开发一个需要配置管理的Go项目,可能涉及用户认证,因此需要处理不同环境的配置。用户可能是开发者,尤其是后端或全栈,可能对Go语言有一定了解,但不太熟悉如何处理配置文件。 首先,需要明确用户的需求:他们可能想了解如何在Go中解析INI文件,有哪些库可用,以及基本的使用方法。用户可能希望得到一个清晰的指南,包括库推荐、代码示例和最佳实践。同时,他们可能关心不同库的优缺点,以便做出选择。 考虑到用户之前的问题涉及安全性,这里可能需要提到配置文件中敏感信息的处理,比如不要将密码明文存储,或者使用环境变量结合配置文件。但用户当前的问题更侧重于解析INI文件本身,所以重点应放在解析方法和库的使用上。 接下来,整理Golang中常用的INI解析库。比如go-ini/ini,这个库功能全面,支持多种数据类型和分区;还有一些其他库,但go-ini可能更主流。需要比较它们的特性,帮助用户选择适合的。另外,可能需要给出安装方法、基本用法示例,比如读取文件、获取值、设置默认值等。 用户可能不知道如何开始,所以步骤要详细。例如,安装库的命令,如何创建和读取INI文件,如何处理不同的数据类型(字符串、整数、布尔值等)。此外,高级功能如分区、自动类型转换、保存配置可能也是用户需要的,但根据用户的提问层次,可能先介绍基础再提到高级内容。 还要考虑最佳实践,比如配置文件的结构建议,安全注意事项,比如不要将配置文件提交到版本库,特别是含有敏感信息时。可能用户需要知道如何管理不同环境的配置(开发、测试、生产),这时候可以提到使用多个INI文件或环境变量覆盖配置。 最后,总结各个库的优缺点,帮助用户根据项目需求选择。比如,go-ini适合复杂需求,而轻量级库适合简单场景。同时,提醒用户注意配置文件的权限和敏感数据处理,呼应之前的安全性话题。</think>### Golang 解析 INI 配置文件的完整指南 INI 是一种简单直观的配置文件格式,常用于存储应用配置参数。以下是 Golang 中处理 INI 文件的常用方法和工具对比: --- #### 一、主流库推荐 1. **go-ini/ini**(推荐) - GitHub: [https://github.com/go-ini/ini](https://github.com/go-ini/ini) - 特点:功能全面,支持自动类型转换、分区嵌套、注释保留等 - 安装: ```bash go get github.com/go-ini/ini ``` 2. **其他轻量级库** - `gopkg.in/ini.v1`(go-ini 的别名) - `github.com/unknwon/goconfig` --- #### 二、基础用法示例 1. **创建 INI 文件** 假设 `config.ini` 内容如下: ```ini [database] host = 127.0.0.1 port = 3306 username = admin password = secret ssl_enabled = true [server] debug_mode = false timeout = 30s # 支持时间单位 ``` 2. **读取配置** ```go package main import ( "fmt" "github.com/go-ini/ini" ) func main() { cfg, err := ini.Load("config.ini") if err != nil { panic(err) } // 读取基础值 dbHost := cfg.Section("database").Key("host").String() dbPort, _ := cfg.Section("database").Key("port").Int() sslEnabled, _ := cfg.Section("database").Key("ssl_enabled").Bool() // 带默认值的读取 timeout := cfg.Section("server").Key("timeout").MustDuration(5 * time.Second) } ``` --- #### 三、高级功能 1. **自动类型转换** ```go // 直接获取对应类型 port := cfg.Section("database").Key("port").MustInt(3306) timeout := cfg.Section("server").Key("timeout").MustDuration(10 * time.Second) ``` 2. **分区嵌套** ```ini [user.profile] name = Alice age = 28 ``` ```go name := cfg.Section("user.profile").Key("name").String() ``` 3. **保存配置** ```go cfg.Section("database").Key("password").SetValue("new_password") err = cfg.SaveTo("config-modified.ini") ``` --- #### 四、最佳实践 1. **配置文件结构建议** ```ini ; 分环境配置(通过命令行参数加载不同文件) [development] db_host = localhost [production] db_host = db.cluster.example.com ``` 2. **敏感信息处理** - **避免明文存储**:将密码/密钥放在环境变量中 - **文件权限**:设置 `chmod 600 config.ini` 3. **结合结构体映射**(go-ini 特性) ```go type DatabaseConfig struct { Host string `ini:"host"` Port int `ini:"port"` Username string `ini:"username"` } var dbConf DatabaseConfig err = cfg.Section("database").MapTo(&dbConf) ``` --- #### 五、对比其他格式 | **格式** | **优点** | **缺点** | |----------|---------------------------|-------------------------| | INI | 简单易读,适合层级少的配置 | 不支持复杂数据结构 | | JSON | 结构化强,支持嵌套 | 无注释功能,可读性稍差 | | YAML | 表达力强,支持多行文本 | 缩进敏感,易出错 | --- #### 六、总结建议 - **选择 go-ini/ini**:适合需要灵活读写、类型转换的场景 - **轻量级场景**:使用标准库 `strings.Split` 手动解析简单配置 - **关键注意点**: - 统一配置文件路径管理(如通过 `-config` 参数指定) - 生产环境禁用 `cfg.SaveTo` 防止意外覆盖 - 结合 `viper` 库可实现多格式配置统一管理
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值