当前位置: 移动技术网 > IT编程>脚本编程>Go语言 > Go语言中INI配置文件格式解析

Go语言中INI配置文件格式解析

2020年05月05日  | 移动技术网IT编程  | 我要评论

init配置文件与解析

ini配置文件有三要素

  1. parameters

  指一条配置,就像key = value这样的。

  1. sections

  sections是parameters的集合,sections必须独占一行并且用[]括起来。

  sections没有明显的结束方式,一个sections的开始就是另一个sections的结束。

  1. comments

  指ini配置文件的注释,以 ; 开头。

[database]
serverip=**********
serverport=8080
controlconnectstring=qwdj7+xh6owaanaghvgh5/5uxyra2rfz/ufakdln1h9tw+v7z0socfr+wydyzcjf/anufpxlo6cldahm4xxmbadyks6zmkwugqngdzmpx6c=
controlconnectcategory=0
 
[logoninfo]
saveuserid=y
userid=admin
dbserver=appdb
dbcenter=demo
 
[userconfig]
opendownloadfileatonec=y
windowstyle=devexpress dark style
 
[language]
language=chs
 
[autoupdate]
version=1.1

init 配置文件的解析

这里我们使用github上的第三方库(https://github.com/go-ini)

img

**package ini provides ini file read and write functionality in go. **

安装

the minimum requirement of go is 1.6.

$ go get gopkg.in/ini.v1

please add -u flag to update in the future.

开始使用

我们将通过一个非常简单的例子来了解如何使用。

首先,我们需要在任意目录创建两个文件(my.inimain.go),在这里我们选择 /tmp/ini 目录。

$ mkdir -p /tmp/ini
$ cd /tmp/ini
$ touch my.ini main.go
$ tree .
.
├── main.go
└── my.ini

0 directories, 2 files

现在,我们编辑 my.ini 文件并输入以下内容(部分内容来自 grafana)。

# possible values : production, development
app_mode = development

[paths]
# path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used)
data = /home/git/grafana

[server]
# protocol (http or https)
protocol = http

# the http port  to use
http_port = 9999

# redirect to correct domain if host header does not match domain
# prevents dns rebinding attacks
enforce_domain = true

很好,接下来我们需要编写 main.go 文件来操作刚才创建的配置文件。

package main

import (
    "fmt"
    "os"

    "gopkg.in/ini.v1"
)

func main() {
    cfg, err := ini.load("my.ini")//初始化一个cfg
    if err != nil {
        fmt.printf("fail to read file: %v", err)
        os.exit(1)
    }

    // 典型读取操作,默认分区可以使用空字符串表示
    fmt.println("app mode:", cfg.section("").key("app_mode").string())
    fmt.println("data path:", cfg.section("paths").key("data").string())

    // 我们可以做一些候选值限制的操作
    fmt.println("server protocol:",
        cfg.section("server").key("protocol").in("http", []string{"http", "https"}))
    // 如果读取的值不在候选列表内,则会回退使用提供的默认值
    fmt.println("email protocol:",
        cfg.section("server").key("protocol").in("smtp", []string{"imap", "smtp"}))

    // 试一试自动类型转换
    fmt.printf("port number: (%[1]t) %[1]d\n", cfg.section("server").key("http_port").mustint(9999))
    fmt.printf("enforce domain: (%[1]t) %[1]v\n", cfg.section("server").key("enforce_domain").mustbool(false))
    
    // 差不多了,修改某个值然后进行保存
    cfg.section("").key("app_mode").setvalue("production")
    cfg.saveto("my.ini.local")
}

运行程序,我们可以看下以下输出

$ go run main.go
app mode: development
data path: /home/git/grafana
server protocol: http
email protocol: smtp
port number: (int) 9999
enforce domain: (bool) true

$ cat my.ini.local
# possible values : production, development
app_mode = production

[paths]
# path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used)
data = /home/git/grafana
...

高级用法

将配制文件映射到结构体

想要使用更加面向对象的方式玩转 ini 吗?好主意。

配置文件如下:

name = unknwon
age = 21
male = true
born = 1993-01-01t20:17:05z

[note]
content = hi is a good man!
cities = hangzhou, boston
//按照配置文件的内容构造结构体
type note struct {
    content string
    cities  []string
}

type person struct {
    name string
    age  int `ini:"age"`//这里需要用到反射,因为和ini文件的字段不同
    male bool
    born time.time
    note
    created time.time `ini:"-"`
}

func main() {
    cfg, err := ini.load("path/to/ini")
    // ...
    p := new(person)//初始化一个结构体,返回指向他的指针
    err = cfg.mapto(p)
    // ...

    // 一切竟可以如此的简单。
    err = ini.mapto(p, "path/to/ini")//核心代码
    // ...

    // 嗯哼?只需要映射一个分区吗?
    n := new(note)
    err = cfg.section("note").mapto(n)
    // ...
}

结构的字段怎么设置默认值呢?很简单,只要在映射之前对指定字段进行赋值就可以了。如果键未找到或者类型错误,该值不会发生改变。

// ...
p := &person{
    name: "joe",
}
// ..

将结构体映射成配置文件

type embeded struct {
    dates  []time.time `delim:"|" comment:"time data"`
    places []string    `ini:"places,omitempty"`
    none   []int       `ini:",omitempty"`
}

type author struct {
    name      string `ini:"name"`
    male      bool
    age       int `comment:"author's age"`
    gpa       float64
    nevermind string `ini:"-"`
    *embeded `comment:"embeded section"`
}

func main() {
    a := &author{"unknwon", true, 21, 2.8, "",
        &embeded{
            []time.time{time.now(), time.now()},
            []string{"hangzhou", "boston"},
            []int{},
        }}
    cfg := ini.empty()//初始化一个空配置文件
    err = ini.reflectfrom(cfg, a)//核心代码
    // ...
}

瞧瞧,奇迹发生了。

name = unknwon
male = true
; author's age
age = 21
gpa = 2.8

; embeded section
[embeded]
; time data
dates = 2015-08-07t22:14:22+08:00|2015-08-07t22:14:22+08:00
places = hangzhou,boston

参考文献:

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网