Dictionary 有没有更好的方法来解析此地图?

Dictionary 有没有更好的方法来解析此地图?,dictionary,go,config,Dictionary,Go,Config,非常新,基本上在我正在编写的实际代码中,我计划从包含环境变量的文件中读取,即API_KEY=XYZ。这意味着我可以让它们脱离版本控制。下面的解决方案“有效”,但我觉得可能有更好的方法 最终目标是能够像这样从文件中访问元素 m[“API_KEY”]这将打印XYZ。这甚至可能已经存在,我正在重新发明轮子,我看到围棋有环境变量,但它似乎不是我特别想要的 因此,我们非常感谢您的帮助 代码: 1-您可以使用csv.NewReader从encoding/csv通过一个函数调用r.ReadAll() r.C

非常新,基本上在我正在编写的实际代码中,我计划从包含环境变量的文件中读取,即
API_KEY=XYZ
。这意味着我可以让它们脱离版本控制。下面的解决方案“有效”,但我觉得可能有更好的方法

最终目标是能够像这样从文件中访问元素
m[“API_KEY”]
这将打印
XYZ
。这甚至可能已经存在,我正在重新发明轮子,我看到围棋有环境变量,但它似乎不是我特别想要的

因此,我们非常感谢您的帮助

代码:


1-您可以使用
csv.NewReader
encoding/csv
通过一个函数调用
r.ReadAll()

r.Comma = '='
r.TrimLeadingSpace = true
结果是
[]字符串
,并且输入顺序被保留,请尝试:

输出:

[[Var1 Value1] [Var2 Value2] [Var3 Value3]]
map[Var2:Value2 Var3:Value3 Var1:Value1]

2-您可以微调
csv.ReadAll()
以将输出转换为映射,但顺序不保留,请尝试:

输出:

[[Var1 Value1] [Var2 Value2] [Var3 Value3]]
map[Var2:Value2 Var3:Value3 Var1:Value1]

首先,我建议阅读以下相关问题:

接下来,我会考虑将配置存储在另一种格式中。因为你的建议不是标准。它接近于,但即使是属性文件也可能包含Unicode序列,因此您的代码不是有效的

.properties
格式解析器,因为它根本不处理Unicode序列

相反,我建议您使用,这样您就可以轻松地用Go或任何其他语言对其进行解析,并且有许多工具可以编辑JSON文本,而且它仍然是人性化的

使用JSON格式,将其解码为
map
只是一个函数调用:。它可能是这样的:

text := `{"Var1":"Value1", "Var2":"Value2", "Var3":"Value3"}`

var m map[string]string
if err := json.Unmarshal([]byte(text), &m); err != nil {
    fmt.Println("Invalid config file:", err)
    return
}

fmt.Println(m)
text := `Var1=Value1
Var2=Value2
Var3=Value3`

scanner := bufio.NewScanner(strings.NewReader(text))

m := map[string]string{}
for scanner.Scan() {
    parts := strings.Split(scanner.Text(), "=")
    if len(parts) == 2 {
        m[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
    }
}
if err := scanner.Err(); err != nil {
    fmt.Println("Error encountered:", err)
}

fmt.Println(m)
输出(在上尝试):

该包将为您处理格式化和转义,因此您不必担心这些问题。它还将为您检测和报告错误。此外,JSON更灵活,您的配置可能包含数字、文本、数组等。所有这些都是免费的,因为您选择了JSON格式

另一种流行的配置格式是,但Go标准库不包括YAML解析器。参见Go实现

如果您不想更改格式,那么我只会使用您发布的代码,因为它正是您希望它做的:逐行处理输入,并解析每行的
name=value
对。它以一种清晰明了的方式做到了这一点。为此目的使用CSV或任何其他读取器都是不好的,因为它们隐藏了隐藏在引擎盖下的内容(它们有意且正确地隐藏了特定于格式的细节和转换)。CSV阅读器首先是CSV阅读器;即使更改制表符/逗号符号:它也将解释某些转义序列,并可能提供与在纯文本编辑器中看到的不同的数据。从您的角度来看,这是一个意外的行为,但是嘿,您的输入不是CSV格式的,但是您要求读者将其解释为CSV

我想为您的解决方案添加的一个改进是使用。它可以用于逐行读取输入,并处理不同样式的换行符序列。它可能是这样的:

text := `{"Var1":"Value1", "Var2":"Value2", "Var3":"Value3"}`

var m map[string]string
if err := json.Unmarshal([]byte(text), &m); err != nil {
    fmt.Println("Invalid config file:", err)
    return
}

fmt.Println(m)
text := `Var1=Value1
Var2=Value2
Var3=Value3`

scanner := bufio.NewScanner(strings.NewReader(text))

m := map[string]string{}
for scanner.Scan() {
    parts := strings.Split(scanner.Text(), "=")
    if len(parts) == 2 {
        m[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
    }
}
if err := scanner.Err(); err != nil {
    fmt.Println("Error encountered:", err)
}

fmt.Println(m)
输出是相同的。试穿一下


使用
bufio.Scanner
还有另一个优点:接受一个“所有东西都是字节源”的通用接口。这意味着,如果您的配置存储在一个文件中,您甚至不必将所有配置读取到内存中,您只需打开该文件,例如,使用该文件返回的值也实现了
io.Reader
,因此您可以直接将
*os.file
值传递给
bufio.NewScanner()
(因此,
bufio.Scanner
将从文件中读取数据,而不是像上面的例子那样从内存缓冲区中读取数据)。

如果它完成了任务,我就不会担心它。Go不是关于优雅的代码,而是关于工作代码……也就是说,在访问它之前,我会对len(tmp)>=2进行测试(
tmp[0]
)因为这可能会失败。@RickyA说得很好,实际上我并没有在那里进行任何错误检查。我将把它添加到我正在进行的工作中,谢谢。如果我还想用
strings.TrimSpace()修剪任何空白,这是一种有趣的方式
是通过元素循环并更新它们,还是有办法将其应用于csv阅读器?只是为了避免出现
[Var2 Value2]
看起来很有趣,我会看看其他人是否有任何建议。如果没有,我稍后会接受这个答案。我真的无法反驳,答案很好。我选择纯文本格式的唯一原因主要是因为我看到它在其他语言中的处理方式。在我消化了你的答案后,我会阅读你提到的其他问题完全回答。谢谢:D@Pigeon进行了更多的编辑,使其更加有用/信息丰富。