英文:
Go parse yaml file
问题
我正在尝试使用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
...
希望对你有帮助!
英文:
I'm trying to parse a yaml file with Go. Unfortunately I can't figure out how. The yaml file I have is this:
---
firewall_network_rules:
rule1:
src: blablabla-host
dst: blabla-hostname
...
I have this Go code, but it does not work:
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)
}
When I run this, I get an error. I think it's because I haven't created a struct for the src and dst key/values. FYI: when I change that to a list, it works.
So above code parses this:
---
firewall_network_rules:
rule1:
- value1
- value2
...
答案1
得分: 47
如果你正在使用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://zhwt.github.io/yaml-to-go/),它可以将YAML转换为Go结构体,只需将你的YAML输入到该服务中,就会得到一个自动生成的结构体。
同样,也有一个JSON的等效工具:https://mholt.github.io/json-to-go/
最后,像之前的帖子所写的那样进行解组:
var service Service
err = yaml.Unmarshal(yourFile, &service)
if err != nil {
panic(err)
}
fmt.Print(service.Metadata.Name)
英文:
If you're working with google cloud or kubernetes more specifically and want to parse a service.yaml like this:
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
Supplying a real world example so you get the hang of how nesting can be written.
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"`
}
There's a convenient service called yaml-to-go https://zhwt.github.io/yaml-to-go/ which converts YAML to go structs, just input your YAML into that service and you get an autogenerated struct.
A JSON equivalent exists aswell: https://mholt.github.io/json-to-go/
And last unmarshal as a previous poster wrote:
var service Service
err = yaml.Unmarshal(yourFile, &service)
if err != nil {
panic(err)
}
fmt.Print(service.Metadata.Name)
答案2
得分: 11
好的,以下是翻译好的代码:
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)
}
希望对你有帮助!如果有其他问题,请随时提问。
英文:
Well, I think I've figured it out by myself. The following piece of code works fine. Any suggestions/improvements?
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)
}
答案3
得分: 10
如果你不关心规则名称,为什么不按照下面的方式组织你的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"`
}
英文:
Why not organize your yaml file like below if you don't care about the rule name?
---
firewall_network_rules:
-
name: rule1
src: blablabla-host
dst: blabla-hostname
-
name: rule2
src: bla-host
dst: bla-hostname
So the code will be like this, it is clean and extensible:
type Rule struct {
Name string `yaml:"name"`
Src string `yaml:"src"`
Dst string `yaml:"dst"`
}
type Config struct {
FirewallNetworkRules []Rule `yaml:"firewall_network_rules"`
}
答案4
得分: 2
如果您的YAML文件是简单的(单层嵌套)如下所示:
mongo:
DB: database
COL: collection
log:
error: log/error/error.log
api:
key: jhgwewbcjwefwjfg
在这种情况下,您可以使用接口(interface)而不是声明结构体(struct)。
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
}
这对于一级嵌套的情况下可以正常工作,如果您有复杂的嵌套,则建议使用struct
。
英文:
If your YAML file is simple (single nesting) like following
mongo:
DB: database
COL: collection
log:
error: log/error/error.log
api:
key: jhgwewbcjwefwjfg
Here, you can use interface instead of declaring struct.
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
}
This works fine for level 1 nesting, if you have complex nesting then it is recommended to use struct
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论