go读取toml格式配置文件

2,160 阅读5分钟

crocodile使用的配置文件格式为toml

说到配置文件格式,主流的有:`JSON、YAML、TOML。

json

JSON的定义一般是作为数据格式,它通常用于序列化、结构化数据并通过网络进行交换,通常发生在服务器与 Web 应用之间。不过也有很多工具将其作为配置文件使用。

其实使用JSON作为配置文件也有其一定的优势:

  • 语法非常简单,纯粹的键值对结构
  • 很多编程语言的标准库都支持 JSON,比如:在JS当中你可以直接引入读取
  • 现在几乎所有的工具都提供 JSON 支持,包括语法突出显示、自动格式化、验证工具等。
  • 采用人类可读的轻量级文本,只需更少的编码,处理速度更快

但是,也因为其独特的定位,它天生就注定了并不适合作为配置文件使用,原因也很明显:

  • 不支持注释:对于配置文件来说,注释的重要性不言而喻,但是JSON不支持添加注释(JSON 作为一种数据交换格式,也不需要注释😅)

  • 语法过于严格:键和字符串必须使用""双引号(其实对于键来说,并不需要使用引号),结尾不允许有逗号(除了结尾都必须有逗号,哈哈~)

  • 多余的最外层大括号:作为配置文件来说,最外层的大括号也显得有些多余(这也是其作为交换数据格式的特点,为了界定不同的对象)

{
"name": "cat",
"desc": { 
    "color": "orange",
    "age": 1 
     }
}

yaml

YAML 是一种数据序列化语言,通常用于编写配置文件(它的流行和 k8s 脱不了关系😏~)。

语法规则:

  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进时不允许使用Tab键,只允许使用空格。
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • # 表示注释,从这个字符一直到行尾,都会被解析器忽略。
  • 文件拓展名为 .yaml.yml

支持的数据格式:

  • 对象:键值对的集合,又称为映射/ 哈希 / 字典
  • 数组:一组按次序排列的值,又称为序列 / 列表
  • 纯量:单个的、不可再分的值,可以理解为基本类型

其特点如下:

  • 有更好的可读性,对用户更友好
  • 简洁和强大,写法简洁,也有复杂的语法支持不同功能
  • 是JSON的超集,JSON 文件在 YAML 中有效
  • 使用 Python 风格的缩进来表示嵌套

如果说到缺点的话,那和它的特点也是密不可分的

  • 因为不是原生支持的格式,不同平台需要专门的解析工具
  • 简单使用,基本语法够简单;但是进阶使用,语法就比较复杂了,对于多行字符串的处理也有待优化,尤其是结合缩进语法一起
  • 缩进语法,如果搞错了缩进或者没看清,够你定位问题的了
# 我是注释
name: cat
desc: 
    color: orange
    age: 1
    date: 2022-09-01 16:10:01

toml

TOML 旨在成为一个语义明显且易于阅读的最小化配置文件格式。TOML 被设计成可以无歧义地映射为哈希表。TOML 应该能很容易地被解析成各种语言中的数据结构。

  • TOML 以人为先

    • 语义明显易于阅读
    • 能无歧义地映射为哈希表
    • 易于解析成各种语言中的数据结构
  • TOML 具备实用的原生类型

    • 键/值对
    • 数组
    • 内联表
    • 表数组
    • 整数 & 浮点数
    • 布尔值
    • 日期 & 时刻,带可选的时区偏移
  • TOML 受到广泛支持

    • TOML 已经拥有大多数当今使用的最流行的编程语言的实现:C、C#、C++、Clojure、Dart、Elixir、Erlang、Go、Haskell、Java、Javascript、Lua、Objective-C、Perl、PHP、Python、Ruby、Swift、Scala……以及更多。

语法规则:

  • 大小写敏感
  • 文件必须是合法的 UTF-8 编码的 Unicode 文档
  • 简洁、清晰的 = 写法(name = "cat"
  • 字符串需要由引号(")包裹
  • 表写法,键值对的集合,由表头定义,连同方括号作为单独的行出现
  • # 表示注释
  • 文件拓展名为 .toml

其特点如下:

  • 写法符合直觉、简单清晰

  • 键名写法强大,键名可以是裸露的,引号引起来的,或点分隔的。

  • 对字符串支持完善,基本字符串、多行基本字符串、字面量和多行字面量

  • 表写法功能强大,键值对、数组、嵌套写法等

# 我是注释
name = "cat"
[desc]
color = "orange"
age = 1
date = 2022-09-01 16:10:01

或者

name = "cat" 
desc.color = "orange"
desc.age = 1
desc.date = 2022-09-01 16:10:01

Toml语法可查看Toml官方文档中文文档。 GO客户端:github.com/BurntSushi/…,这里是官方使用示例

安装go-toml包

# 安装toml-go客户端
go get github.com/BurntSushi/toml

# 验证toml语法
go get github.com/BurntSushi/toml/cmd/tomlv
tomlv some-toml-file.toml

demo

# 全局信息
title = "TOML示例"

# 应用信息
[app]
    author = "史布斯"
    organization = "Mafool"
    mark = "第一行\n第二行."            # 换行
    release = 2020-05-27T07:32:00Z   # 时间

# 数据库配置
[mysql]
    server = "192.168.1.1"
    ports = [ 8001, 8001, 8002 ]     # 数组
    connection_max = 5000
    enabled = true

# Redis主从                           # 字典对象
[redis]
    [redis.master]
        host = "10.0.0.1"
        port = 6379
    [redis.slave]
        host = "10.0.0.1"
        port = 6380

# 二维数组
[releases]
release = ["dev", "test", "stage", "prod"]
tags = [["dev", "stage", "prod"],[2.2, 2.1]]


# 公司信息                             #对象嵌套
[company]
    name = "xx科技"
[company.detail]
    type = "game"
    addr = "北京朝阳"
    icp = "030173"

package main

import (
	"fmt"
	"github.com/BurntSushi/toml"
	"time"
)

type Config struct {
	Title    string
	App      app
	DB       mysql `toml:"mysql"`
	Redis    map[string]redis
	Releases releases
	Company  Company
}

type app struct {
	Author  string
	Org     string `toml:"organization"`
	Mark    string
	Release time.Time
}

type mysql struct {
	Server  string
	Ports   []int
	ConnMax int `toml:"connection_max"`
	Enabled bool
}

type redis struct {
	Host string
	Port int
}

type releases struct {
	Release []string
	Tags    [][]interface{}
}

type Company struct {
	Name   string
	Detail detail
}

type detail struct {
	Type string
	Addr string
	ICP  string
}

func main() {
	var config Config
	if _, err := toml.DecodeFile("example.toml", &config); err != nil {
		panic(err)
	}

	fmt.Printf("全局信息: %+v\n\n", config.Title)

	fmt.Printf("App信息:%+v\n\n", config.App)

	fmt.Printf("Mysql配置:%+v\n\n", config.DB)

	fmt.Printf("版本信息:%+v\n\n", config.Releases)

	fmt.Printf("Redis主从:%+v\n\n", config.Redis)

	fmt.Printf("企业信息:%+v\n\n", config.Company)
}