TOML(Tom's Obvious, Minimal Language)
TOML(Tom's Obvious, Minimal Language)是一种配置文件格式,设计目标是一眼能读懂、好写也好解析。它的语法源自 INI 文件,但支持更复杂的结构,语法规则也更严格。
1. TOML 文件格式
TOML 文件格式的基本组成包括:
键值对(Key-Value Pairs):
- TOML 文件使用键值对来表示数据。键和值之间用等号(
=)分隔。例如:tomlkey = "value"
- TOML 文件使用键值对来表示数据。键和值之间用等号(
节(Tables):
- TOML 文件使用节来组织配置数据,节用方括号(
[])表示。例如:toml[section] key = "value"
- TOML 文件使用节来组织配置数据,节用方括号(
子节(Subtables):
- TOML 支持嵌套节,允许在节中定义子节。例如:toml
[parent] key = "value" [parent.child] key = "value"
- TOML 支持嵌套节,允许在节中定义子节。例如:
数组(Arrays):
- TOML 支持一维数组和多维数组。例如:toml
array = [1, 2, 3]
- TOML 支持一维数组和多维数组。例如:
日期和时间(Date and Time):
- TOML 支持 ISO 8601 格式的日期和时间。例如:toml
date = 2024-07-25 datetime = 2024-07-25T14:30:00
- TOML 支持 ISO 8601 格式的日期和时间。例如:
注释(Comments):
- 注释以井号(
#)开头,注释内容被忽略。例如:toml# This is a comment key = "value"
- 注释以井号(
多行字符串(Multiline Strings):
- TOML 支持多行字符串,以三个双引号(
""")括起来。例如:tomlmultiline_string = """ This is a multiline string """
- TOML 支持多行字符串,以三个双引号(
2. TOML 文件的示例
以下是一个示例 TOML 文件,展示了各种功能:
toml
# This is a TOML file example
[server]
host = "localhost"
port = 8080
[database]
user = "admin"
password = "secret"
dbname = "example_db"
[features]
enabled = true
version = 1.0
[paths]
data = "/path/to/data"
logs = "/path/to/logs"
[servers]
[servers.alpha]
ip = "192.168.1.1"
port = 9000
[servers.beta]
ip = "192.168.1.2"
port = 9001
[[items]]
name = "Item1"
value = 10
[[items]]
name = "Item2"
value = 20- [server]:节名,用于定义服务器配置。
- [database]:节名,用于定义数据库配置。
- [features]:节名,用于定义特性开关和版本。
- [paths]:节名,用于定义路径配置。
- [servers]:节名,包含子节
alpha和beta,用于定义多个服务器配置。 - [[items]]:数组节,每个数组元素表示一个项。
3. TOML 的优点和缺点
优点:
人类可读:
- 纯文本格式,读起来和编辑都容易。
支持复杂数据结构:
- TOML 支持嵌套节、数组和多行字符串,适合表达复杂的配置数据。
语法规则严格:
- 规则明确,解析时歧义少,出错的可能性小。
缺点:
有限的工具支持:
- 尽管 TOML 得到了一定的支持,但与一些更常见的格式(如 JSON、YAML)相比,支持工具和库相对较少。
不支持自定义数据类型:
- TOML 不支持自定义数据类型或结构,只能使用基本类型(字符串、整数、浮点数、布尔值、日期等)。
4. TOML 文件的应用
TOML 最常见的用途是应用程序配置,用来定义程序的参数和选项;系统设置、服务配置和开发环境配置里也常用,只要数据是结构化的就合适。
5. TOML 文件处理示例(Go 语言)
在 Go 语言中,可以使用第三方库(如 github.com/pelletier/go-toml)来处理 TOML 文件。以下是一个示例代码,展示了如何读取和写入 TOML 文件。
读取 TOML 文件示例:
读取要求当前目录已有 config.toml,可以先运行下面的写入示例生成,也可以手写一份,例如:
toml
[server]
host = "localhost"
port = 8080go
package main
import (
"fmt"
"log"
"github.com/pelletier/go-toml"
)
func main() {
// 读取 TOML 文件
data, err := toml.LoadFile("config.toml")
if err != nil {
log.Fatalf("Failed to read file: %v", err)
}
// 读取节
server := data.Get("server").(*toml.Tree)
// 读取键值对,注意 TOML 中的整数会被解析为 int64
host := server.Get("host").(string)
port := server.Get("port").(int64)
fmt.Printf("Host: %s\n", host)
fmt.Printf("Port: %d\n", port)
}输出:
plaintext
Host: localhost
Port: 8080写入 TOML 文件示例:
go
package main
import (
"log"
"os"
"github.com/pelletier/go-toml"
)
func main() {
// 用 TreeFromMap 从 map 构建 TOML 树
data, err := toml.TreeFromMap(map[string]interface{}{
"server": map[string]interface{}{
"host": "localhost",
"port": 8080,
},
"database": map[string]interface{}{
"user": "admin",
"password": "secret",
},
})
if err != nil {
log.Fatalf("Failed to build tree: %v", err)
}
// 通过 WriteTo 把 TOML 树写入文件
file, err := os.Create("config.toml")
if err != nil {
log.Fatalf("Failed to create file: %v", err)
}
defer file.Close()
if _, err := data.WriteTo(file); err != nil {
log.Fatalf("Failed to save file: %v", err)
}
log.Println("TOML 文件保存成功")
}6. TOML 文件处理中的常见问题
节的命名:
- 确保节名符合 TOML 的语法要求,不包含非法字符或空格。
数据类型的转换:
- TOML 支持基本数据类型,但在读取和写入时需要正确处理类型转换。
文件编码:
- 确保 TOML 文件使用 UTF-8 编码,以避免字符编码问题。
数组的处理:
- 处理数组时,确保正确使用双括号(
[[...]])语法,并处理数组元素的排序和重复问题。
- 处理数组时,确保正确使用双括号(
总结
TOML 的语法规则明确,节、数组、日期这些结构都能表达,Go 侧用 github.com/pelletier/go-toml 这类库即可读写。工具和库的支持不如 JSON、YAML 普遍,但在配置文件这个场景里够用。