Dawn's Blogs

分享技术 记录成长

0%

GO语言杂谈 (6) go-ini的使用

介绍

go-ini官方网站

ini文件

ini格式的文件是配置文件中常用的格式。

  • 在ini文件中,每个键值对占用一行,中间使用=隔开
  • #开头的为注释
  • ini文件是以分区为组织的,分区以[name]作为标志
1
2
3
4
5
6
7
8
9
[mysql]
ip = 127.0.0.1
port = 3306
user = root
password = 123456
database = test

[kafka]
address = 127.0.0.1:9092

go-ini

go-ini为GO语言提供了读写ini文件的功能。如使用go-ini读取上面的配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
"fmt"
"github.com/go-ini/ini"
)

func main() {
// 加载配置文件
cfg, err := ini.Load("conf.ini")
if err != nil {
fmt.Println("Load config file failed, err:", err)
}

// 获取配置文件信息

// [mysql]分区
mysqlSection := cfg.Section("mysql")
mysqlIP := mysqlSection.Key("ip").String()
fmt.Println("mysql ip =", mysqlIP)
mysqlPort, err := mysqlSection.Key("port").Int()
if err != nil {
fmt.Println("mysql port parse failed, err:", err)
}
fmt.Println("mysql port =", mysqlPort)

// [kafka]分区
kafkaAddress := cfg.Section("kafka").Key("address").String()
fmt.Println("kafka address=", kafkaAddress)
}

使用go-ini读取配置文件的步骤如下:

  • 调用ini.Load加载配置文件,得到配置对象cfg
  • 调用cfg.Section获取分区对象,使用Key方法得到对应配置项的对象
  • Key对象需根据类型调用对应的方法返回具体类型,可以使用StringIntFloat64等方法。

配置文件中存储的都是字符串,所以类型为字符串的配置项不会出现类型转换失败的,故String方法只返回一个值。但是IntUint等方法可能会转换失败,返回一个值和一个错误。

如果每次取值都需要进行错误判断,那么代码写起来会非常繁琐。go-ini为此提供了对应的MustType方法(Type为Int/Uint/Float64等),这个方法只返回一个值。同时它接收可变参数,如果类型无法转换,取参数中第一个值返回,并且该参数设置为这个配置的值,下次调用返回这个值。

go-ini使用

分区操作

获取信息

在加载配置之后

  • 通过Sections方法获取所有分区
  • SectionStrings()方法获取所有的分区名
  • Section(name)获取名为name的分区,如果该分区不存在,则自动创建一个分区并返回
  • NewSection(name)手动创建一个新分区,如果分区已存在,则返回错误

父子分区

可以在分区名中使用.表示两个或多个分区之间的父子关系。

例如package.sub的父分区为packagepackage的父分区为默认分区。如果某个键在子分区中不存在,则会在它的父分区中再次查找,直到没有父分区为止。

保存配置

可以将生成的配置对象写入到文件中,保存有两种类型的接口,一种直接保存到文件,另一种写入到io.Writer中:

1
2
3
4
5
err = cfg.SaveTo("my.ini")
err = cfg.SaveToIndent("my.ini", "\t") // 有缩进

cfg.WriteTo(writer)
cfg.WriteToIndent(writer, "\t") // 有缩进

*Indent方法会对分区下的键进行缩进。

分区与结构体字段映射

定义结构变量,加载完配置文件后,调用MapTo将配置项赋值到结构变量的对应字段中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
type Config struct {
MySQL MySQLConfig `ini:"mysql"`
Kafka KafkaConfig `ini:"kafka"`
}

type MySQLConfig struct {
IP string `ini:"ip"`
Port int `ini:"port"`
User string `ini:"user"`
Password string `ini:"password"`
Database string `ini:"database"`
}

type KafkaConfig struct {
Address string `ini:"address"`
}

func main() {
cfg, err := ini.Load("conf.ini")
if err != nil {
fmt.Println("Load config file failed, err:", err)
}

// 映射整个配置文件
c := &Config{}
cfg.MapTo(c)
fmt.Println(c)

// 只映射mysql分区
mysql := &MySQLConfig{}
cfg.Section("mysql").MapTo(mysql)
fmt.Println(mysql)
}

也可以通过结构体生成配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
func NewIni() {
cfg := ini.Empty()
// 构造配置信息
c := Config{
MySQL: MySQLConfig{
IP: "192.168.1.2",
Port: 3306,
User: "Dawn",
Password: "123456",
Database: "dbname",
},
Kafka: KafkaConfig{
Address: "127.0.0.1:9092",
},
}

// 通过结构体生成配置
err := ini.ReflectFrom(cfg, &c)
if err != nil {
fmt.Println("ReflectFrom failed: ", err)
return
}

// 保存到文件
err = cfg.SaveTo("new-conf.ini")
if err != nil {
fmt.Println("SaveTo failed: ", err)
return
}

}