在 Go HTML 模板中创建结构映射键的语法
Syntax for creating struct map key in Go HTML template
我正在编写一个简单的 Go 程序来显示每个环境的 HTML table 已部署服务版本。我的程序包含以下结构:
type versionKey struct {
Environment string
Service string
}
type templateData struct {
Environments []string
Services []string
Versions map[versionKey]string
}
如您所见,Versions
映射使用 versionKey
作为字符串值的键,例如"1.0.0"
.
我正在将 templateData
结构传递给 HTML 模板并遍历其 Environments
和 Services
切片以构建 HTML table。问题是我需要为任何给定的环境和服务交集构建一个 versionKey
,这样我就可以使用它从 Versions
映射中查找版本并在 [=37= 中输出该值] 单元格。
在模板中,我有范围内可用的 $environment
和 $service
变量,但我无法使用 Go 模板语法来创建 versionKey
结构。
这是省略了标记的模板代码:
{{$environments := .Environments}}
{{$services := .Services}}
{{$versions := .Versions}}
{{range $service := $services}}
...
{{range $environment := $environments}}
...
{{index $versions ...? }} // How to create versionKey struct map key here?
...
{{end}}
...
{{end}}
仅使用模板代码是不行的。您需要执行 Go 代码的某种支持才能做到这一点。根据设计理念,模板不应包含复杂的逻辑。你可能会争论这是否复杂,但模板语法不支持这一点。
最简单的解决方案是向 templateData
结构添加一个 Version()
方法,这将简单地 return 给定环境和服务的版本:
func (t *templateData) Version(environment, service string) string {
return t.Versions[versionKey{
Environment: environment,
Service: service,
}]
}
从模板中使用:
{{range $service := $services -}}
{{range $environment := $environments}}
{{$environment}} - {{$service}} version: {{$.Version $environment $service}}
{{end}}
{{end}}
正在测试:
t := template.Must(template.New("").Parse(templ))
td := &templateData{
Environments: []string{"EnvA", "EnvB"},
Services: []string{"ServA", "ServB"},
Versions: map[versionKey]string{
{"EnvA", "ServA"}: "1.0.0",
{"EnvA", "ServB"}: "1.0.1",
{"EnvB", "ServA"}: "1.0.2",
},
}
if err := t.Execute(os.Stdout, td); err != nil {
panic(err)
}
输出(在 Go Playground 上尝试):
EnvA - ServA version: 1.0.0
EnvB - ServA version: 1.0.2
EnvA - ServB version: 1.0.1
EnvB - ServB version:
备选方案
而不是 templateData.Version()
方法,您可以轻松地注册一个函数,该函数可以从给定的环境和服务中创建和 return 类型 versionKey
的值。参见 Template.Funcs()
for details. This would be more complicated though, but more flexible as this could be reused elsewhere. See an example of this here: 。一个细微的变化是将函数值作为任何其他模板数据传递,而不是将其注册为可以调用的命名函数。
另一种选择是 "transform" 您的 Versions
字段到地图的地图中,例如:
Versions map[string]map[string]string
首先可以按环境索引,然后按服务索引,在模板中可以通过 2 个 {{index}}
操作来实现。不过,您必须检查第一个索引是否产生任何结果。
我正在编写一个简单的 Go 程序来显示每个环境的 HTML table 已部署服务版本。我的程序包含以下结构:
type versionKey struct {
Environment string
Service string
}
type templateData struct {
Environments []string
Services []string
Versions map[versionKey]string
}
如您所见,Versions
映射使用 versionKey
作为字符串值的键,例如"1.0.0"
.
我正在将 templateData
结构传递给 HTML 模板并遍历其 Environments
和 Services
切片以构建 HTML table。问题是我需要为任何给定的环境和服务交集构建一个 versionKey
,这样我就可以使用它从 Versions
映射中查找版本并在 [=37= 中输出该值] 单元格。
在模板中,我有范围内可用的 $environment
和 $service
变量,但我无法使用 Go 模板语法来创建 versionKey
结构。
这是省略了标记的模板代码:
{{$environments := .Environments}}
{{$services := .Services}}
{{$versions := .Versions}}
{{range $service := $services}}
...
{{range $environment := $environments}}
...
{{index $versions ...? }} // How to create versionKey struct map key here?
...
{{end}}
...
{{end}}
仅使用模板代码是不行的。您需要执行 Go 代码的某种支持才能做到这一点。根据设计理念,模板不应包含复杂的逻辑。你可能会争论这是否复杂,但模板语法不支持这一点。
最简单的解决方案是向 templateData
结构添加一个 Version()
方法,这将简单地 return 给定环境和服务的版本:
func (t *templateData) Version(environment, service string) string {
return t.Versions[versionKey{
Environment: environment,
Service: service,
}]
}
从模板中使用:
{{range $service := $services -}}
{{range $environment := $environments}}
{{$environment}} - {{$service}} version: {{$.Version $environment $service}}
{{end}}
{{end}}
正在测试:
t := template.Must(template.New("").Parse(templ))
td := &templateData{
Environments: []string{"EnvA", "EnvB"},
Services: []string{"ServA", "ServB"},
Versions: map[versionKey]string{
{"EnvA", "ServA"}: "1.0.0",
{"EnvA", "ServB"}: "1.0.1",
{"EnvB", "ServA"}: "1.0.2",
},
}
if err := t.Execute(os.Stdout, td); err != nil {
panic(err)
}
输出(在 Go Playground 上尝试):
EnvA - ServA version: 1.0.0
EnvB - ServA version: 1.0.2
EnvA - ServB version: 1.0.1
EnvB - ServB version:
备选方案
而不是 templateData.Version()
方法,您可以轻松地注册一个函数,该函数可以从给定的环境和服务中创建和 return 类型 versionKey
的值。参见 Template.Funcs()
for details. This would be more complicated though, but more flexible as this could be reused elsewhere. See an example of this here:
另一种选择是 "transform" 您的 Versions
字段到地图的地图中,例如:
Versions map[string]map[string]string
首先可以按环境索引,然后按服务索引,在模板中可以通过 2 个 {{index}}
操作来实现。不过,您必须检查第一个索引是否产生任何结果。