首页 > 其他分享 >GO读取toml格式文件

GO读取toml格式文件

时间:2022-11-15 10:35:01浏览次数:91  
标签:name err fmt 格式文件 go toml GO string

在toml以 # 作为注释,文件内容也是需要有一个 section 其下内容以 key = value 书写,key不能为空,但是可以是空引号,key可以用双引号也可以不用,value是字符串时需要用双引号引起来

不能多次定义同一个key

如果定义来一个值为 mysql.name = "name" 那么 就不能在定义 mysql = "xx"

toml的语法可以去官网看看 https://toml.io/cn/

toml格式

规格

  • TOML 是大小写敏感的。
  • TOML 文件必须是合法的 UTF-8 编码的 Unicode 文档。
  • 空白是指制表符(0x09)或空格(0x20)。
  • 换行是指 LF(0x0A)或 CRLF(0x0D0A)。

一个小例子

[project]
name = "spam"
version = "2020.0.0"
description = "Lovely Spam! Wonderful Spam!"
readme = "README.rst"
requires-python = ">=3.8"
license = {file = "LICENSE.txt"}
keywords = ["egg", "bacon", "sausage"]

它和ini格式的配置文件几乎一模一样。

但是在TOML中,数据类型非常丰富:

  • 字符串
  • 注释
  • 数字
  • 布尔值
  • 数组
  • 哈希表
  • 时间格式

1、注释

TOML 认为配置文件都应当支持注释。

# 这是一条 TOML 注释

# 这是一个多行的
# TOML 注释

2、字符串

如果你是从ini格式转过来的,一定要注意字符串值要加引号。

键默认会当成字符串处理,可以加也可以不加

加引号的键叫引号键(Quoted Key),不加引号的键叫裸键(Bare Key)

TOML 格式非常灵活,对于灵活的语言,最好的方式是给自己设置规范和纪律,一直用好一种用法,不然很容易学废。

官方推荐我们尽量用裸键,当裸键不能正确表达意思的时候,再用引号键。

name = "spam"     #OK  裸键
name_1 = spam     #错误
"name_2" = "spam" #OK  引号键

裸键只能包含 ASCII 字母,ASCII 数字,下划线和短横线(A-Za-z0-9_-),引号键则可以支持特殊字符,甚至是空格。

当键中包含特殊字符的时候,使用引号键。

'name@! erf:' = 'spam' # OK
name@! erf: = 'spam'   # 错误

当字符串为多行字符串时使用三引号,会自动换行:

name = """
this is a
new line 
command"""

得到的结果是:

this is a
new line
command

如果不想自动换行,只是想增强可读性,可以使用折行符号\

name = """
this is a \
new line \
command"""

得到结果是不换行的:

this is a new line command

3、数字

# 整数
int1 = +99
int2 = 42
int3 = 0
int4 = -17

# 十六进制带有前缀 `0x`
hex1 = 0xDEADBEEF
hex2 = 0xdeadbeef
hex3 = 0xdead_beef

# 八进制带有前缀 `0o`
oct1 = 0o01234567
oct2 = 0o755

# 二进制带有前缀 `0b`
bin1 = 0b11010110

# 小数
float1 = +1.0
float2 = 3.1415
float3 = -0.01

# 指数
float4 = 5e+22
float5 = 1e06
float6 = -2E-2

# both
float7 = 6.626e-34

# 分隔符
float8 = 224_617.445_991_228

# 无穷
infinite1 = inf # 正无穷
infinite2 = +inf # 正无穷
infinite3 = -inf # 负无穷

# 非数
not1 = nan
not2 = +nan
not3 = -nan 

toml除了支持10进制表示,还支持二进制(0b)八进制(0o)十六进制(0x)

age1 = 0b11
age2 = 0o12
age3 = 0xb

上面的解析结果为:

{
  	'age1': 3, 
	'age2': 10, 
	'age3': 11
}

4、布尔

bool1 = true
bool2 = false

5、时间

时间类型是toml的一大特色,因为绝大多数的配置文件格式都是不支持时间类型的。

toml 遵循的是 RFC 3339 时间格式,只要照着格式写,解析出来会自动转成编程语言的时间类型。

ts = 2021-01-06 07:30:00
ts1 = 2021-01-06 07:30:00.1234
time1 = 07:30:00

得到的结果:

{
	'ts': datetime.datetime(2021, 1, 6, 7, 30), 
	'ts1': datetime.datetime(2021, 1, 6, 7, 30, 0, 123000),
	'time1': datetime.time(7, 30)
}

TOML 支持日期、时刻、日期时刻,带或者不带时区偏移。

# 坐标日期时刻
odt1 = 1979-05-27T07:32:00Z
odt2 = 1979-05-27T00:32:00-07:00
odt3 = 1979-05-27T00:32:00.999999-07:00

# 各地日期时刻
ldt1 = 1979-05-27T07:32:00
ldt2 = 1979-05-27T00:32:00.999999

# 各地日期
ld1 = 1979-05-27

# 各地时刻
lt1 = 07:32:00
lt2 = 00:32:00.999999

6、数组

数组可以是同类型数据,可以换行,也可以嵌套,和python当中列表简直一模一样。

但是要注意,尽量保持元素是同类型的数据

users = [
	['iswy', '男'],
	['you', '女'],
]

得到的结果:

{
	'users': [
		['iswy', '男'], 
		['you', '女']
	]
}

7、哈希表

表有点类似于python中的字典

user = {name='iswy', gender='男'}

得到的结果:

{
	'user': {
		'gender': '男', 
		'name': 'iswy'
	}
}

这种写在key后面的表叫内联表

还有一种用法,类似于ini格式中的section,用于分组管理,暂且把它叫做外联表

比如上面的例子,可以换一种形式,得到的结果是完全一样的。

[user]
gender = '男'
name = 'iswy'

表支持嵌套,子表可以缩进也可以不缩进

[user]
  cat = ['admin', 'normal']

  [user.student]
  name='iswy'
  age=19

  [user.teacher]
  name='you'
  age=32

如果你觉得这种风格你不喜欢,也可以换成下面的风格:

[user]
cat = ['admin', 'normal']

# student
student.name='iswy'
student.age=19

# teacher
teacher.name='you'
teacher.age=328

上面的并不是键值,属于子健

一定要注意,当键包含. 号时,一定要加引号

site.'x.com' = 'http://x.com'

表和数组的配套使用

最后我们要考虑的问题是当有多个用户需要配置,我们要使用表数组进行分组

[[user]] 
  [user.student]
  name='iswy'
  age=19

  [user.teacher]
  name='you'
  age=328

[[user]]
  [user.student]
  name='iswy2'
  age=192

  [user.teacher]
  name='you2'
  age=3282

得到的结果:

{
	'user': [
		{
			'student': {'age': 19, 'name': 'iswy'},
			'teacher': {'age': 328, 'name': 'you'}
		},
		{
			'student': {'age': 192, 'name': 'iswy2'},
			'teacher': {'age': 3282, 'name': 'you2'}
		}
	]
}

文件扩展名

TOML 文件应当使用 .toml 扩展名。

MIME 类型

在互联网上传输 TOML 文件时,恰当的 MIME 类型是 application/toml

Go语言支持的库

GitHub

范例文件

1.toml

os="windows"
version="10"
[server]
addr="192.168.1.1"
port="80"
http="https"
route="/test/indes"

github.com/pelletier/go-toml

这个有两种版本

版本1是可以直接读取文件,而且不用新建结构体

版本2已经不允许直接读取文件了

安装

版本1

$ go get github.com/pelletier/go-toml

版本2

$ go get github.com/pelletier/go-toml/v2

解组

反序列化

版本1直接读取文件

可以不用结构体,直接读取

package main

import (
	"fmt"

	"github.com/pelletier/go-toml"
)

func main() {
	config, _ := toml.LoadFile("1.toml") //加载toml文件
	key := config.Get("os")              //读取一级key
	fmt.Println(key)
	/*
		windows
	*/
	key = config.Get("server") //读取复合的一级
	fmt.Println(key)
	/*
		addr = "192.168.1.1"
		http = "https"
		port = "80"
		route = "/test/indes"
	*/
	key = config.Get("server.addr") //读取二级key
	fmt.Println(key)
	/*
		192.168.1.1
	*/
	key = config.Get("abc") //读取不存在的key不会报错
	fmt.Println(key)
	/*
		<nil>
	*/
}

版本1和版本2都可以使用结构体解组

package main

import (
	"fmt"
	"os"

	"github.com/pelletier/go-toml"
)

type Conf struct {
	Os      string `toml:"os"`
	Version string `toml:"version"`
	Server  `toml:"server"`
}
type Server struct {
	Addr  string `toml:"addr"`
	Port  string `toml:"port"`
	Http  string `toml:"http"`
	Route string `toml:"route"`
}

func main() {
	var conf Conf
    //打开文件
	file, err := os.Open("1.toml")
	if err != nil {
		fmt.Println(err)
		return
	}
    defer file.Close()
    //读取文件并解组到结构体
	err = toml.NewDecoder(file).Decode(&conf)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%+v\n", conf)
}
/*
	{Os:windows Version:10 Server:{Addr:192.168.1.1 Port:80 Http:https Route:/test/indes}}
*/

如果是读取字符串

package main

import (
	"fmt"
	"os"

	"github.com/pelletier/go-toml/v2"
)


func main() {
	doc := `
	version = 2
	name = "go-toml"
	tags = ["go", "toml"]
	`
	type MyConfig struct {
		Version int
		Name    string
		Tags    []string
	}

	var cfg MyConfig
    //反序列化
	err = toml.Unmarshal([]byte(doc), &cfg)
	if err != nil {
		panic(err)
	}
	fmt.Println("version:", cfg.Version)
	fmt.Println("name:", cfg.Name)
	fmt.Println("tags:", cfg.Tags)
	/*
		version: 2
		name: go-toml
		tags: [go toml]
	*/
}

编组

序列化

package main

import (
	"fmt"

	"github.com/pelletier/go-toml"
)

func main() {
	type MyConfig struct {
		Version int
		Name    string
		Tags    []string
	}
	cfg := MyConfig{
		Version: 2,
		Name:    "go-toml",
		Tags:    []string{"go", "toml"},
	}
	b, err := toml.Marshal(cfg)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
	/*
		Name = "go-toml"
		Tags = ["go", "toml"]
		Version = 2
	*/
}

工具

Go-toml 提供了三个方便的命令行工具:

  • tomljson:读取 TOML 文件并输出其 JSON 表示形式。

    $ go install github.com/pelletier/go-toml/v2/cmd/tomljson@latest
    $ tomljson --help
    
  • jsontoml:读取 JSON 文件并输出 TOML 表示形式。

    $ go install github.com/pelletier/go-toml/v2/cmd/jsontoml@latest
    $ jsontoml --help
    
  • tomll:检查并重新格式化 TOML 文件。

    $ go install github.com/pelletier/go-toml/v2/cmd/tomll@latest
    $ tomll --help
    

github.com/BurntSushi/toml

安装

$ go get github.com/BurntSushi/toml

带有一个TOML验证器CLI工具

$ go install github.com/BurntSushi/toml/cmd/tomlv@latest
$ tomlv some-toml-file.toml

读取文件

package main

import (
	"fmt"
	"os"

	"github.com/BurntSushi/toml"
)

type Conf struct {
	Os      string `toml:"os"`
	Version string `toml:"version"`
	Server  `toml:"server"`
}
type Server struct {
	Addr  string `toml:"addr"`
	Port  string `toml:"port"`
	Http  string `toml:"http"`
	Route string `toml:"route"`
}

func main() {
	var conf Conf
	file, err := os.Open("1.toml")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()
    //读取文件
	_, err = toml.DecodeFile("1.toml", &conf)
	fmt.Printf("%+v\n", conf)
	/*
		{Os:windows Version:10 Server:{Addr:192.168.1.1 Port:80 Http:https Route:/test/indes}}
	*/
	if err != nil {
		fmt.Println(err)
		return
	}
}

读取字符串

package main

import (
	"fmt"
	"time"

	"github.com/BurntSushi/toml"
)

func main() {
	tomlData := `Age = 25
	Cats = [ "Cauchy", "Plato" ]
	Pi = 3.14
	Perfection = [ 6, 28, 496, 8128 ]
	DOB = 1987-07-05T05:45:00Z
	`
	type Config1 struct {
		Age        int
		Cats       []string
		Pi         float64
		Perfection []int
		DOB        time.Time
	}

	var conf1 Config1
	_, err = toml.Decode(tomlData, &conf1)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%+v\n", conf1)
    
    //或者使用Unmarshal
    var conf2 Config1
	err = toml.Unmarshal([]byte(tomlData), &conf2)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%+v\n", conf1)
}

标签:name,err,fmt,格式文件,go,toml,GO,string
From: https://www.cnblogs.com/hexug/p/16891540.html

相关文章

  • GO 你知道吗【5】
    GO你知道吗函数的接收者,效果在同一个go文件中方法名相同,返回值相同,接收者不同这个接收者机制类似于隐式多态......
  • mongodb通过非映射方式操作documnet
    前言我是MongoDB小白,刚开始学。不过,我猜大多数使用MongoDB的,都是采用映射方式处理的,即需要有定义好的用于映射的实体类。但是这样的话,如果表的结构在未来可能频繁变......
  • django的日志管理-logging
    django的日志使用python的logging模块logging的四个模块---logger-记录器:日志系统的入口,每个logger都是bucket,可以向这个bucket写入需要处理的信息,logger根据消息的日志......
  • Do a good job: When boss tell you to print a doc file.
    Bosstellmetoprinterprintafile,buthedon'tsaydetaileddetail.Whenshopmanageraskmeprintonbothsides?Ihavetoaskbossafterhehadassigned......
  • 5.golang变量的数据类型
    1.基本数据类型数值型 a.整数类型              A.各整数类型分“有符号和无符号,intun......
  • 11-Go语言进阶-01
    包的使用引入时,用.做前缀,使用时可以省略包名,不建议这么使用可以前缀别名"_"下划线操作,可以执行包里面对应的init函数首字母大写的字段和实体,才能被外部引用init函数......
  • Go的ORM安装使用
    源码开发      安装包管理第三方模块goenv-wGO111MODULE=ongomodinitgowebgomodtidygorunmain.go初始化go项目步骤     goe......
  • 4.go中的变量
    1.变量表示内存中的一个存储区域2.该区域有自己的名称(变量名)和类型(数据类型)3.使用的三种方式 指定变量类型,声明后若不赋值,使用默认值根据值自行判定变量类型(类型推导......
  • Mongodb集群搭建
    mongodb的集群搭建方式主要有三种,主从模式,Replicaset模式,sharding模式,三种模式各有优劣,适用于不同的场合,属Replicaset应用最为广泛,主从模式现在用的较少,sharding模式最......
  • Go语言的一些资料汇总
    1. ​​8分钟了解你为什么应该学习Go语言 ​​​​https://www.bilibili.com/video/av45561733/​​2.​​手把手教你从零开始搭建Go语言开发环境​​​​https:/......