在GO模板中对结构使用范围

时间:2018-10-12 09:42:52

标签: loops go struct yaml go-templates

我从values.yaml解析结构,并想在template.yaml中使用它

这是我的values.yaml文件:

services:
  app:
    image: matryoshka/app
    replicaCount: 1
  cron:
    image: matryoshka/cron
    replicaCount: 1

这是我的template.yaml(无效代码):

{{- range $key, $value := .Services}}
    {{$key}}{{$value}}
{{- end}}

哪个给我错误:

panic: template: template.yaml:1:26: executing "template.yaml" at <.Services>: range can't iterate over {{atryoshka/app 1} {matryoshka/cron 1}}

这是我的.go代码:

package main

import (
    "html/template"
    "io/ioutil"
    "os"
    "path/filepath"

    "gopkg.in/yaml.v2"
)

type Values struct {
    Services struct {
        App struct {
            Image        string `yaml:"image"`
            ReplicaCount string `yaml:"replicaCount"`
        } `yaml:"app"`
        Cron struct {
            Image        string `yaml:"image"`
            ReplicaCount string `yaml:"replicaCount"`
        } `yaml:"cron"`
    }
}

func parseValues() Values {

    var values Values
    filename, _ := filepath.Abs("./values.yaml")
    yamlFile, err := ioutil.ReadFile(filename)

    err = yaml.Unmarshal(yamlFile, &values)
    if err != nil {
        panic(err)
    }

    return values

}
func insertValues(class Values) {
    paths := []string{"template.yaml"}
    t, err := template.New(paths[0]).ParseFiles(paths...)
    if err != nil {
        panic(err)
    }
    err = t.Execute(os.Stdout, class)
    if err != nil {
        panic(err)
    }
}

func main() {
    values := parseValues()
    insertValues(values)
}

如何正确遍历.Services中的template.yaml?我发现{{- range $key, $value := .Services}}仅提供选项,但不起作用。

1 个答案:

答案 0 :(得分:2)

如您所见,您不能在结构的各个字段范围内移动。您只能在切片,数组,地图和通道上进行选择。

使用地图

最简单的方法就是传递:一张地图。您可以将YAML直接解组到地图或空接口中:

func parseValues() interface{} {
    var values interface{}
    // ...rest is unchanged
}

func insertValues(class interface{}) {
    // ...unchanged
}

稍微更改模板的格式(请注意.services

{{- range $key, $value := .services}}
{{$key}} {{$value}}
{{- end}}

使用这些,它的工作原理是:

app map[replicaCount:1 image:matryoshka/app]
cron map[image:matryoshka/cron replicaCount:1]

使用切片

如果您想继续使用Services模型,另一种选择是手动准备并传递一部分字段:

insertValues([]interface{}{values.Services.App, values.Services.Cron})

然后是模板:

{{- range $key, $value := .}}
{{$key}} {{$value}}
{{- end}}

然后输出:

0 {matryoshka/app 1}
1 {matryoshka/cron 1}

使用切片和反射

如果您希望它保持“动态”状态(这意味着您不必手动枚举字段),则可以创建一个使用反射来执行此操作的帮助器函数。有关如何执行此操作的示例,请参见Get all fields from an interfaceIterate through the fields of a struct in Go