去解析yaml文件
Posted
技术标签:
【中文标题】去解析yaml文件【英文标题】:Go parse yaml file 【发布时间】:2015-04-25 06:54:07 【问题描述】:我正在尝试使用 Go 解析 yaml 文件。不幸的是,我无法弄清楚如何。我的yaml文件是这样的:
---
firewall_network_rules:
rule1:
src: blablabla-host
dst: blabla-hostname
...
我有这个 Go 代码,但它不起作用:
package main
import (
"fmt"
"io/ioutil"
"path/filepath"
"gopkg.in/yaml.v2"
)
type Config struct
Firewall_network_rules map[string][]string
func main()
filename, _ := filepath.Abs("./fruits.yml")
yamlFile, err := ioutil.ReadFile(filename)
if err != nil
panic(err)
var config Config
err = yaml.Unmarshal(yamlFile, &config)
if err != nil
panic(err)
fmt.Printf("Value: %#v\n", config.Firewall_network_rules)
当我运行它时,我得到一个错误。我认为这是因为我还没有为 src 和 dst 键/值创建结构。仅供参考:当我将其更改为列表时,它可以工作。
所以上面的代码解析了这个:
---
firewall_network_rules:
rule1:
- value1
- value2
...
【问题讨论】:
【参考方案1】:如果您更具体地使用 google cloud 或 kubernetes,并希望像这样解析 service.yaml:
apiVersion: v1
kind: Service
metadata:
name: myName
namespace: default
labels:
router.deis.io/routable: "true"
annotations:
router.deis.io/domains: ""
spec:
type: NodePort
selector:
app: myName
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
提供一个真实世界的示例,以便您了解如何编写嵌套。
type Service struct
APIVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Metadata struct
Name string `yaml:"name"`
Namespace string `yaml:"namespace"`
Labels struct
RouterDeisIoRoutable string `yaml:"router.deis.io/routable"`
`yaml:"labels"`
Annotations struct
RouterDeisIoDomains string `yaml:"router.deis.io/domains"`
`yaml:"annotations"`
`yaml:"metadata"`
Spec struct
Type string `yaml:"type"`
Selector struct
App string `yaml:"app"`
`yaml:"selector"`
Ports []struct
Name string `yaml:"name"`
Port int `yaml:"port"`
TargetPort int `yaml:"targetPort"`
NodePort int `yaml:"nodePort,omitempty"`
`yaml:"ports"`
`yaml:"spec"`
有一个名为 yaml-to-go https://yaml.to-go.online/ 的便捷服务将 YAML 转换为 go 结构,只需将您的 YAML 输入到该服务中,您就会得到一个自动生成的结构。
最后解组,正如之前的海报所写:
var service Service
err = yaml.Unmarshal(yourFile, &service)
if err != nil
panic(err)
fmt.Print(service.Metadata.Name)
【讨论】:
【参考方案2】:如果您不关心规则名称,为什么不按如下方式组织您的 yaml 文件?
---
firewall_network_rules:
-
name: rule1
src: blablabla-host
dst: blabla-hostname
-
name: rule2
src: bla-host
dst: bla-hostname
所以代码会是这样,干净且可扩展:
type Rule struct
Name string `yaml:"name"`
Src string `yaml:"src"`
Dst string `yaml:"dst"`
type Config struct
FirewallNetworkRules []Rule `yaml:"firewall_network_rules"`
【讨论】:
【参考方案3】:嗯,我想我已经自己想通了。以下代码可以正常工作。有什么建议/改进吗?
package main
import (
"fmt"
"io/ioutil"
"path/filepath"
"gopkg.in/yaml.v2"
)
type Config struct
Firewall_network_rules map[string]Options
type Options struct
Src string
Dst string
func main()
filename, _ := filepath.Abs("./fruits.yml")
yamlFile, err := ioutil.ReadFile(filename)
if err != nil
panic(err)
var config Config
err = yaml.Unmarshal(yamlFile, &config)
if err != nil
panic(err)
fmt.Printf("Value: %#v\n", config.Firewall_network_rules)
【讨论】:
尝试更惯用的FirewallNetworkRules
并添加一个结构标记来捕获 YAML 格式 - 例如` yaml:"firewall_network_rules"
` 有关 YAML 库中结构标记用法的文档,请参见此处:godoc.org/gopkg.in/yaml.v2#Marshal
感谢您的建议,它确实澄清了我的代码。【参考方案4】:
如果您的 YAML 文件很简单(单嵌套),如下所示
mongo:
DB: database
COL: collection
log:
error: log/error/error.log
api:
key: jhgwewbcjwefwjfg
在这里,你可以使用接口而不是声明结构。
main()
config := Config()
mongoConfig := config["mongo"]
mongo.MongoDial(
String(
Get(mongoConfig, "DB")
),
String(
Get(mongoConfig, "COL")
)
)
func Config() map[string]interface
filename, _ := filepath.Abs("configs/config.yaml")
yamlFile, err := ioutil.ReadFile(filename)
if err != nil
panic(err)
var config map[string]interface
err = yaml.Unmarshal(yamlFile, &config)
if err != nil
panic(err)
return config
func Get(this interface, key string) interface
return this.(map[interface]interface)[key]
func String(payload interface) string
var load string
if pay, oh := payload.(string); oh
load = pay
else
load = ""
return load
这适用于 1 级嵌套,如果您有复杂的嵌套,建议使用struct
。
【讨论】:
以上是关于去解析yaml文件的主要内容,如果未能解决你的问题,请参考以下文章