在 GO 模板中使用 range over struct
Use range over struct in 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)
}
如何正确地在 template.yaml
中迭代 .Services
?我只找到 {{- range $key, $value := .Services}}
的选项,但它不起作用。
您不能像您所经历的那样遍历结构的字段。您只能对切片、数组、映射和通道进行范围。
使用地图
最简单的方法就是通过:一张地图。您可以直接将 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}
使用切片和反射
如果您希望它保持 "dynamic"(意味着您不必手动枚举字段),您可以创建一个辅助函数,它使用反射来完成。有关如何执行此操作的示例,请参阅 and Iterate through the fields of a struct in Go.
我从 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)
}
如何正确地在 template.yaml
中迭代 .Services
?我只找到 {{- range $key, $value := .Services}}
的选项,但它不起作用。
您不能像您所经历的那样遍历结构的字段。您只能对切片、数组、映射和通道进行范围。
使用地图
最简单的方法就是通过:一张地图。您可以直接将 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}
使用切片和反射
如果您希望它保持 "dynamic"(意味着您不必手动枚举字段),您可以创建一个辅助函数,它使用反射来完成。有关如何执行此操作的示例,请参阅