我正在尝试访问Yaml文件并获取单独的值,但我正在努力使用Struct语法来实现这一点。下面的代码处理Yaml,我可以打印完整的结构,但是如何访问单个的ecs.services.name属性?
任何关于如何处理这个问题的建议都是值得欢迎的,因为我已经遇到了几个Yaml库,但它们中的任何一个都无法充分发挥作用。
test.yaml:
ecs:
services:
- name: my-service
taskDefinition: my-task-def
desiredCount: 1Yaml.go
package main
import (
"fmt"
"io/ioutil"
"path/filepath"
"gopkg.in/yaml.v2"
)
type Config struct {
//Ecs []map[string]string this works for ecs with name
Ecs struct {
Services []struct {
Name string
TaskDefinition string
DesiredCount int
}
}
//Services []map[string][]string
}
func main() {
filename, _ := filepath.Abs("test.yaml")
yamlFile, err := ioutil.ReadFile(filename)
check(err)
var config Config
err = yaml.Unmarshal(yamlFile, &config)
check(err)
fmt.Printf("Description: %#v\n", config.Ecs.Services)
}
func check(e error) {
if e != nil {
panic(e)
}
}输出
$ go run yaml.go
Description: []struct { Name string; TaskDefinition string; DesiredCount int }{struct { Name string; TaskDefinition string; DesiredCount int }{Name:"my-service", TaskDefinition:"", DesiredCount:0}}发布于 2017-11-09 09:47:23
我有一个类似的要求,在yaml文件上,我需要执行嵌套检索。由于我发现没有开箱即用的解决方案,所以我不得不自己写。
我有一个yaml文件,其内容如下
"a": "Easy!"
"b":
"c": "2"
"d": ["3", "4"]
"e":
"f": {"g":"hi","h":"6"}我想从这个结构中访问和打印嵌套值,输出应该如下所示
--- yaml->a: Easy!
--- yaml->b->c: 2
--- yaml->b->x: None //not existing in the yaml
--- yaml->y->w: None //not existing in the yaml
--- yaml->b->d[0]: 3 //accessing value from a list
--- yaml->e->f->g: hi 我也不想定义一个结构来保存解析的yaml。golang中最通用的结构是接口{}。yaml最适合的结构是map[interface{}]interface{}。对于来自java的人来说,这类似于Map<Object,Object>。一旦数据被解封,我必须编写一个函数,它可以使用嵌套键遍历结构并返回值。
下面是执行此操作的代码。打开注释并执行,以了解代码如何遍历嵌套结构并最终获得值。虽然本例假设yaml中的所有值都是字符串,但也可以对数值键和值进行扩展。
package main
import (
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
"reflect"
)
func main() {
testFile := "test.yaml"
testYaml, rerr := ioutil.ReadFile(testFile)
if rerr != nil {
fmt.Errorf("error reading yaml file: %v", rerr)
}
m := make(map[interface{}]interface{})
if uerr := yaml.Unmarshal([]byte(testYaml), &m); uerr != nil {
fmt.Errorf("error parsing yaml file: %v", uerr)
}
fmt.Printf("--- yaml->a: %v\n\n", getValue(m, []string{"a"}, -1)) //single value in a map
fmt.Printf("--- yaml->b->c: %v\n\n", getValue(m, []string{"b", "c"}, -1)) //single value in a nested map
fmt.Printf("--- yaml->b->x: %v\n\n", getValue(m, []string{"b", "x"}, -1)) //value for a non existent nest key
fmt.Printf("--- yaml->y->w: %v\n\n", getValue(m, []string{"y", "w"}, -1)) //value for a non existent nest key
fmt.Printf("--- yaml->b->d[0]: %v\n\n", getValue(m, []string{"b", "d"}, 0))
fmt.Printf("--- yaml->e->f->g: %v\n\n", getValue(m, []string{"e", "f", "g"}, -1))
}
func getValue(obj map[interface{}]interface{}, keys []string, indexOfElementInArray int) string {
//fmt.Printf("--- Root object:\n%v\n\n", obj)
value := "None"
queryObj := obj
for i := range keys {
if queryObj == nil {
break
}
if i == len(keys)-1 {
break
}
key := keys[i]
//fmt.Printf("--- querying for sub object keyed by %v\n", key)
if queryObj[key] != nil {
queryObj = queryObj[key].(map[interface{}]interface{})
//fmt.Printf("--- Sub object keyed by %v :\n%v\n\n", key, queryObj)
} else {
//fmt.Printf("--- No sub object keyed by %v :\n%v\n\n", key)
break
}
}
if queryObj != nil {
lastKey := keys[len(keys)-1]
//fmt.Printf("--- querying for value keyed by %v\n", lastKey)
if queryObj[lastKey] != nil {
objType := reflect.TypeOf(queryObj[lastKey])
//fmt.Printf("Type of value %v\n", objType)
if objType.String() == "[]interface {}" {
//fmt.Printf("Object is a array %v\n", objType)
tempArr := queryObj[lastKey].([]interface{})
//fmt.Printf("Length of array is %v\n", len(tempArr))
if indexOfElementInArray >= 0 && indexOfElementInArray < len(tempArr) {
value = queryObj[lastKey].([]interface{})[indexOfElementInArray].(string)
}
} else {
value = queryObj[lastKey].(string)
}
}
}
return value
}发布于 2016-07-11 19:28:32
您应该使用struct标记,因为您用小写字母命名字段。这也适用于不同的命名字段。
请参阅如何解决此问题的示例:https://play.golang.org/p/WMmlQsqYeB其他答案是不正确的。
发布于 2016-07-11 15:43:17
我觉得你有额外的筑巢能力。可能不需要Config结构。您能否尝试以下定义:
type Ecs struct {
Services []Service
}
type Service struct {
Name string
TaskDefinition string
DesiredCount int
}然后尝试解压缩yaml数据。然后,您可以以ecs.Services的形式访问数据。
https://stackoverflow.com/questions/38310894
复制相似问题