如何使用 toml 文件?

huangapple go评论82阅读模式
英文:

(Go) How to use toml files?

问题

标题上写着,我想知道如何在Golang中使用toml文件。

在此之前,我展示一下我的toml示例。是否正确?

[datatitle]
enable = true
userids = [
    "12345", "67890"
]

[datatitle.12345]
prop1 = 30
prop2 = 10

[datatitle.67890]
prop1 = 30
prop2 = 10

然后,我想将这些数据设置为结构体类型。

最终,我想要按照以下方式访问子元素。

datatitle["12345"].prop1
datatitle["67890"].prop2

提前感谢!

英文:

As title, I want to know how to use toml files from golang.

Before that, I show my toml examples. Is it right?

[datatitle]
enable = true
userids = [
    "12345", "67890"
]
    [datatitle.12345]
    prop1 = 30
    prop2 = 10

    [datatitle.67890]
    prop1 = 30
    prop2 = 10

And then, I want to set these data as type of struct.

As a result I want to access child element as below.

datatitle["12345"].prop1
datatitle["67890"].prop2

Thanks in advance!

答案1

得分: 10

首先获取BurntSushi的toml解析器:

go get github.com/BurntSushi/toml

BurntSushi解析toml并将其映射到结构体,这正是你想要的。

然后执行以下示例并从中学习:

package main

import (
	"github.com/BurntSushi/toml"
	"log"
)

var tomlData = `title = "config"
[feature1]
enable = true
userids = [
  "12345", "67890"
]

[feature2]
enable = false`

type feature1 struct {
	Enable  bool
	Userids []string
}

type feature2 struct {
	Enable bool
}

type tomlConfig struct {
	Title string
	F1    feature1 `toml:"feature1"`
	F2    feature2 `toml:"feature2"`
}

func main() {
	var conf tomlConfig
	if _, err := toml.Decode(tomlData, &conf); err != nil {
		log.Fatal(err)
	}
	log.Printf("title: %s", conf.Title)
	log.Printf("Feature 1: %#v", conf.F1)
	log.Printf("Feature 2: %#v", conf.F2)
}

注意tomlData以及它如何映射到tomlConfig结构体。

在https://github.com/BurntSushi/toml上查看更多示例。

英文:

First get BurntSushi's toml parser:

go get github.com/BurntSushi/toml

BurntSushi parses toml and maps it to structs, which is what you want.

Then execute the following example and learn from it:

package main

import (
	"github.com/BurntSushi/toml"
	"log"
)

var tomlData = `title = "config"
[feature1]
enable = true
userids = [
  "12345", "67890"
]

[feature2]
enable = false`

type feature1 struct {
	Enable  bool
	Userids []string
}

type feature2 struct {
	Enable bool
}

type tomlConfig struct {
	Title string
	F1    feature1 `toml:"feature1"`
	F2    feature2 `toml:"feature2"`
}

func main() {
	var conf tomlConfig
	if _, err := toml.Decode(tomlData, &conf); err != nil {
		log.Fatal(err)
	}
	log.Printf("title: %s", conf.Title)
	log.Printf("Feature 1: %#v", conf.F1)
	log.Printf("Feature 2: %#v", conf.F2)
}

Notice the tomlData and how it maps to the tomlConfig struct.

See more examples at https://github.com/BurntSushi/toml

答案2

得分: 4

2019年的一个小更新 - 现在有一个比BurntSushi/toml更新的替代品,它具有更丰富的API来处理**.toml**文件:

pelletier/go-toml(以及文档

例如,有一个名为config.toml的文件(或者在内存中):

[postgres]
user = "pelletier"
password = "mypassword"

除了将整个配置文件进行常规的编组和解组(可以在接受的答案中看到),使用pelletier/go-toml,你还可以像这样查询单个值:

config, err := toml.LoadFile("config.toml")

if err != nil {
    fmt.Println("Error ", err.Error())
} else {

    // 直接获取数据

    directUser := config.Get("postgres.user").(string)
    directPassword := config.Get("postgres.password").(string)
    fmt.Println("User is", directUser, " and password is", directPassword)

    // 或者使用中间对象

    configTree := config.Get("postgres").(*toml.Tree)
    user := configTree.Get("user").(string)
    password := configTree.Get("password").(string)
    fmt.Println("User is", user, " and password is", password)

    // 显示元素在文件中的位置

    fmt.Printf("User position: %v\n", configTree.GetPosition("user"))
    fmt.Printf("Password position: %v\n", configTree.GetPosition("password"))

    // 使用查询来收集元素,而无需遍历树

    q, _ := query.Compile("$..[user,password]")
    results := q.Execute(config)
    for ii, item := range results.Values() {
        fmt.Println("Query result %d: %v", ii, item)
    }
}

更新

<s>还有spf13/viper,它可以处理.toml配置文件(以及其他支持的格式),但在许多情况下可能有点过度设计。</s>

更新2

Viper实际上不是一个替代品(感谢@GoForth)。

英文:

A small update for the year 2019 - there is now newer alternative to BurntSushi/toml with a bit richer API to work with .toml files:

pelletier/go-toml (and documentation)

For example having config.toml file (or in memory):

[postgres]
user = &quot;pelletier&quot;
password = &quot;mypassword&quot;

apart from regular marshal and unmarshal of the entire thing into predefined structure (which you can see in the accepted answer) with pelletier/go-toml you can also query individual values like this:

config, err := toml.LoadFile(&quot;config.toml&quot;)

if err != nil {
    fmt.Println(&quot;Error &quot;, err.Error())
} else {

    // retrieve data directly

    directUser := config.Get(&quot;postgres.user&quot;).(string)
    directPassword := config.Get(&quot;postgres.password&quot;).(string)
    fmt.Println(&quot;User is&quot;, directUser, &quot; and password is&quot;, directPassword)

    // or using an intermediate object

    configTree := config.Get(&quot;postgres&quot;).(*toml.Tree)
    user := configTree.Get(&quot;user&quot;).(string)
    password := configTree.Get(&quot;password&quot;).(string)
    fmt.Println(&quot;User is&quot;, user, &quot; and password is&quot;, password)

    // show where elements are in the file

    fmt.Printf(&quot;User position: %v\n&quot;, configTree.GetPosition(&quot;user&quot;))
    fmt.Printf(&quot;Password position: %v\n&quot;, configTree.GetPosition(&quot;password&quot;))

    // use a query to gather elements without walking the tree

    q, _ := query.Compile(&quot;$..[user,password]&quot;)
    results := q.Execute(config)
    for ii, item := range results.Values() {
        fmt.Println(&quot;Query result %d: %v&quot;, ii, item)
    }
}

UPDATE

<s>There is also spf13/viper that works with .toml config files (among other supported formats), but it might be a bit overkill in many cases.</s>

UPDATE 2

Viper is not really an alternative (credits to @GoForth).

答案3

得分: 3

这个问题是使用推荐的包BurntSushi/toml解决的!我按照以下方式进行了操作,并且这是代码的一部分。

[toml示例]

[title]
enable = true
[title.clientinfo.12345]
distance = 30
some_id = 6

[Golang示例]

type TitleClientInfo struct {
    Distance int    `toml:"distance"`
    SomeId  int     `toml:"some_id"`
}

type Config struct {
    Enable     bool     `toml:"enable"`
    ClientInfo map[string]TitleClientInfo `toml:"clientinfo"`
}

var config Config
_, err := toml.Decode(string(d), &config)

然后,它可以按照我期望的方式使用。

config.ClientInfo[12345].Distance

谢谢!

英文:

This issue was solved using recommended pkg BurntSushi/toml!!
I did as below and it's part of code.

[toml example]

[title]
enable = true
[title.clientinfo.12345]
distance = 30
some_id = 6

[Golang example]

type TitleClientInfo struct {
    Distance int    `toml:&quot;distance&quot;`
    SomeId  int     `toml:&quot;some_id&quot;`
}

type Config struct {
    Enable     bool     `toml:&quot;enable&quot;`
    ClientInfo map[string]TitleClientInfo `toml:&quot;clientinfo&quot;`
}

var config Config
_, err := toml.Decode(string(d), &amp;config)

And then, it can be used as I expected.

config.ClientInfo[12345].Distance

Thanks!

答案4

得分: 2

使用解决方案Viper,您可以使用JSON、TOML、YAML、HCL、INI等属性格式的配置文件。

创建文件:

./config.toml

首次导入:

import (config &quot;github.com/spf13/viper&quot;)

初始化:

config.SetConfigName(&quot;config&quot;)
config.AddConfigPath(&quot;.&quot;)
err := config.ReadInConfig()
if err != nil {             
	log.Println(&quot;ERROR&quot;, err.Error())
}

获取值:

config.GetString(&quot;datatitle.12345.prop1&quot;)
config.Get(&quot;datatitle.12345.prop1&quot;).(int32)

文档:https://github.com/spf13/viper

示例:https://repl.it/@DarlanD/Viper-Examples#main.go

英文:

With solution Viper you can use a configuration file in JSON, TOML, YAML, HCL, INI and others properties formats.

Create file:

./config.toml

First import:

import (config &quot;github.com/spf13/viper&quot;)

Initialize:

config.SetConfigName(&quot;config&quot;)
config.AddConfigPath(&quot;.&quot;)
err := config.ReadInConfig()
if err != nil {             
	log.Println(&quot;ERROR&quot;, err.Error())
}

And get the value:

config.GetString(&quot;datatitle.12345.prop1&quot;)
config.Get(&quot;datatitle.12345.prop1&quot;).(int32)

Doc.: https://github.com/spf13/viper

e.g.: https://repl.it/@DarlanD/Viper-Examples#main.go

答案5

得分: 0

我正在使用spf13/viper

第三方包

状态 项目 Stars Forks
存活 spf13/viper 如何使用 toml 文件? 如何使用 toml 文件?
存活 BurntSushi/toml 如何使用 toml 文件? 如何使用 toml 文件?

viper的用法

我尝试使用表格将代码和配置文件的内容放在一起,但显然,编辑与最终结果不匹配,所以我将图片放在上面,希望这样更容易比较。

如何使用 toml 文件?


package main
import (
    "github.com/spf13/viper"
    "log"
    "os"
)
func main() {
    check := func(err error) {
        if err != nil {
            panic(err)
        }
    }
    myConfigPath := "test_config.toml"
    fh, err := os.OpenFile(myConfigPath, os.O_RDWR, 0666)
    check(err)
    viper.SetConfigType("toml") // 不要忽略
    err = viper.ReadConfig(fh)
    check(err)

    // 读取
    log.Printf("%#v", viper.GetString("title"))                 // "my config"
    log.Printf("%#v", viper.GetString("DataTitle.12345.prop1")) // "30"
    log.Printf("%#v", viper.GetString("dataTitle.12345.prop1")) // "30"  // 不区分大小写
    log.Printf("%#v", viper.GetInt("DataTitle.12345.prop1"))    // 30
    log.Printf("%#v", viper.GetIntSlice("feature1.userids"))    // []int{456, 789}

    // 写入
    viper.Set("database", "newuser")
    viper.Set("owner.name", "Carson")
    viper.Set("feature1.userids", []int{111, 222}) // 覆盖
    err = viper.WriteConfigAs(myConfigPath)
    check(err)
}

<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th>(写入前)<br>test_config.toml</th>
<th>(写入后)<br>test_config.toml</th>
</tr>
</thead>
<tbody>
<tr>

<td>

title = "my config"

[datatitle]

  [datatitle.12345]
    prop1 = 30

[feature1]
  userids = [456,789]

</td>
<td>

database = "newuser"  # 新增
title = "my config"

[datatitle]

  [datatitle.12345]
    prop1 = 30

[feature1]
  userids = [111,222]  # 更新

[owner]  # 新增
  name = "Carson"

</td>

</tr>
</tbody>
</table>
</div>

英文:

I am using spf13/viper

3rd packages

Status Project Starts Forks
Alive spf13/viper 如何使用 toml 文件? 如何使用 toml 文件?
Alive BurntSushi/toml 如何使用 toml 文件? 如何使用 toml 文件?

usage of viper

I tried to use a table to put the code and the contents of the configuration file together, but obviously, the editing did not match the final result, so I put the image up in the hope that it would make it easier for you to compare

如何使用 toml 文件?


package main
import (
    &quot;github.com/spf13/viper&quot;
    &quot;log&quot;
    &quot;os&quot;
)
func main() {
    check := func(err error) {
        if err != nil {
            panic(err)
        }
    }
    myConfigPath := &quot;test_config.toml&quot;
    fh, err := os.OpenFile(myConfigPath, os.O_RDWR, 0666)
    check(err)
    viper.SetConfigType(&quot;toml&quot;) // do not ignore
    err = viper.ReadConfig(fh)
    check(err)

    // Read
    log.Printf(&quot;%#v&quot;, viper.GetString(&quot;title&quot;))                 // &quot;my config&quot;
    log.Printf(&quot;%#v&quot;, viper.GetString(&quot;DataTitle.12345.prop1&quot;)) // &quot;30&quot;
    log.Printf(&quot;%#v&quot;, viper.GetString(&quot;dataTitle.12345.prop1&quot;)) // &quot;30&quot;  // case-insensitive
    log.Printf(&quot;%#v&quot;, viper.GetInt(&quot;DataTitle.12345.prop1&quot;))    // 30
    log.Printf(&quot;%#v&quot;, viper.GetIntSlice(&quot;feature1.userids&quot;))    // []int{456, 789}

    // Write
    viper.Set(&quot;database&quot;, &quot;newuser&quot;)
    viper.Set(&quot;owner.name&quot;, &quot;Carson&quot;)
    viper.Set(&quot;feature1.userids&quot;, []int{111, 222}) // overwrite
    err = viper.WriteConfigAs(myConfigPath)
    check(err)
}

<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th>(Write Before)<br>test_config.toml</th>
<th>(After)<br>test_config.toml</th>
</tr>
</thead>
<tbody>
<tr>

<td>

title = &quot;my config&quot;

[datatitle]

  [datatitle.12345]
    prop1 = 30

[feature1]
  userids = [456,789]

</td>
<td>

database = &quot;newuser&quot;  # New
title = &quot;my config&quot;

[datatitle]

  [datatitle.12345]
    prop1 = 30

[feature1]
  userids = [111,222]  # Update

[owner]  # New
  name = &quot;Carson&quot;

</td>

</tr>
</tbody>
</table>
</div>

答案6

得分: 0

我正在使用这个1 go-toml库。

它非常适合我的需求。我使用go-toml编写了这个2 go工具来处理containerd的config.toml文件。

1https://github.com/pelletier/go-toml

2https://github.com/prakashmirji/toml-configer

英文:

I am using this 1 go-toml library.

It works great for my uses. I wrote this 2 go util to deal with containerd config.toml file using go-toml

1https://github.com/pelletier/go-toml

2https://github.com/prakashmirji/toml-configer

huangapple
  • 本文由 发表于 2015年12月16日 16:50:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/34307488.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定