首页 > 解决方案 > 写入 TOML 文件时发现重复键;tree.Has() 没有按预期工作

问题描述

在使用 go-toml 解析器写入 TOML 文件时,我看到所有重复的条目。关于 tree.WriteTo() 函数,哪一个是正确的?一个。覆盖文件 b 中的字段。将树附加到文件中?即,对现有文件,再次写入树内容。

我想实现对现有配置参数(存在于 TOML 文件中)的更新操作。

我试过这个:

//Read the config file
tree, _ := toml.LoadFile("/home/robot/test.toml")

//Read user input
reqBody, err := ioutil.ReadAll(r.Body)
                if err != nil {
                        log.Fatal(err)
                }

//Check whether the input config parameter is present in the file or not
configArray := strings.Split(string(reqBody), ";")
                for index, each := range configArray {
                        config := strings.Split(each, "=")
                        fmt.Println("Param name : ", config[0])
                        fmt.Println("Param value  : ", config[1])
                        fmt.Println(index)
                        isPresent := tree.Has(config[0])
                        fmt.Println(isPresent)
                        if isPresent == true {
                                tree.Set(config[0], config[1])
                        }else {
                                fmt.Println("Config Parameter not found")
                        }
                }

// Now the tree has updated values, update the file.
outputReader, err = os.OpenFile("/home/robot/test.toml",os.O_RDWR,0644)
                if err != nil {
                        fmt.Println("Error opening the file")
                }
                var numBytes  int64
                numBytes, err = tree.WriteTo(outputReader)
                if err != nil {
                        fmt.Println("Error writing to the file")
                }
                fmt.Println(numBytes)
  1. tree.Has() 总是返回 false,即使提供了有效的密钥。不知道为什么!请查看粘贴的输出日志。
  2. tree.WriteTo() 将所有树条目附加到文件中。即,它不是更新参数值,而是写入新的所有内容,从而导致文件中的配置参数重复。

如果 tree.WriteTo() 旨在将整个树内容写入文件,那么是否有任何 API 或方法来更新 TOML 文件中的现有配置?

输出日志:

TOML 内容(即树的转储):

Sep 03 13:27:33 mn-0 janus[31157]: [http]
Sep 03 13:27:33 mn-0 janus[31157]:   enableAudit = true
Sep 03 13:27:33 mn-0 janus[31157]:   idleTimeout = "600s"
Sep 03 13:27:33 mn-0 janus[31157]:   logLevel = "debug"
Sep 03 13:27:33 mn-0 janus[31157]:   port = 443
Sep 03 13:27:33 mn-0 janus[31157]:   readTimeout = "10s"
Sep 03 13:27:33 mn-0 janus[31157]:   tlsMode = true
Sep 03 13:27:33 mn-0 janus[31157]:   writeTimeout = "10s"
Sep 03 13:27:33 mn-0 janus[31157]:   [http.cred]
Sep 03 13:27:33 mn-0 janus[31157]:     sessionValidity = "1h"
Sep 03 13:27:33 mn-0 janus[31157]:     strictSecureMode = false
Sep 03 13:27:33 mn-0 janus[31157]:     users = ["robot"]
Sep 03 13:27:33 mn-0 janus[31157]:   [http.ipConfig]
Sep 03 13:27:33 mn-0 janus[31157]:     ipAddr = ""
Sep 03 13:27:33 mn-0 janus[31157]:     role = "ssh"

输入无效键:

Sep 03 13:27:33 mn-0 janus[31157]: Param name :  http.enableAudt
Sep 03 13:27:33 mn-0 janus[31157]: Param value  :   true
Sep 03 13:27:33 mn-0 janus[31157]: 0
Sep 03 13:27:33 mn-0 janus[31157]: false

输入有效密钥:

Sep 03 13:27:33 mn-0 janus[31157]: Param name :   http.enableAudit 
Sep 03 13:27:33 mn-0 janus[31157]: Param value  :   false
Sep 03 13:27:33 mn-0 janus[31157]: 1
Sep 03 13:27:33 mn-0 janus[31157]: false
  1. 还有一个关于 unmarshal() 或阅读时配置验证的问题,说我的结构是这样的。

    type IPConfig struct { 用户字符串 角色字符串 IPAddr 字符串 }

    类型 MyConfiguration 结构 { MyConfiguration MyConfiguration }

一个。如果 TOML 文件有这个:

[ipConfig]
    role = "ssh"
    ipAddr  = ""

即,它没有更多参数“用户”。我如何在 Unmarshal 时捕捉到这个?至少 Unmarshal() 不会在这里抛出任何错误。

湾。如果 TOML 文件有这个:

[ipConfig]
    role = "ssh"
    ipAddr  = ""
    user = "lauren"
    abc = "xyz"

即,它有额外的配置参数“abc”。如何抓住这个?即使为此,Unmarshal() 也没有抛出任何错误。

有什么办法可以得到这些验证错误?

标签: gotoml

解决方案


对于问题 1:

如果无法访问文件的内容,很难弄清楚可能发生了什么。如果您认为这是一个错误,请在 Github 上打开一个问题,包括复制步骤。谢谢!

对于问题 2:

您需要在写入文件之前删除截断文件。

Go-toml 不知道您正在写入文件。WriteTo接受 a io.Writer,它只是表示“你可以写的东西”。因此,当您打开文件进行读/写时,文件的“作者”部分的偏移量为 0。因此,当 toml 写入它(使用WriteTo)时,它只会将字节替换到文件中。

如果要使用 覆盖文件的内容,则WriteTo需要.truncate(0)在写入文件之前调用或类似的方法。

注意:在撰写本文时,评论在Load. Github 上有一个问题要求该功能。

对于问题 3:

不支持在缺少键或额外键时出错。目前存在一个支持后者的问题


推荐阅读