我是一个新手 Go(和 Go 模板)业余程序员,我看到有人问过这个问题的变体,但从来没有完全以同样的方式,所以又来了……
我正在尝试在不注册任何其他功能的情况下执行以下操作(因此,将自己严格限制在有限的模板语法允许的范围内):
假设我有几个不同的 HTML 片段,每个片段都有自己的模板:A.tpl
、、B.tpl
等等C.tpl
(数量不固定,随着应用程序的增长,它会随着时间的推移而增长;此外,在示例可能暗示的子模板)。
然后我有一个主模板,它设置了常见的页眉、页脚、菜单等,以及围绕每个的必要 HTML,in main.tpl
,非常简单,如下所示:
{{ if .A }}
{{ template "A.tpl" . }}
{{ end }}
{{ if .B }}
{{ template "B.tpl" . }}
{{ end }}
{{ if .C }}
{{ template "C.tpl" . }}
{{ end }}
...
或者,根据调用代码的完成方式,这也可以写成(假设我们将子模板的名称作为值传递给main.tpl
):
{{ if eq .SubTemplate "A.tpl" }}
{{ template "A.tpl" . }}
{{ end }}
{{ if eq .SubTemplate "B.tpl" }}
{{ template "B.tpl" . }}
{{ end }}
{{ if eq .SubTemplate "C.tpl" }}
{{ template "C.tpl" . }}
{{ end }}
...
显然,写(在模板级别)显而易见的是:
{{ template .SubTemplate . }}
但当然这在语法上是无效的,因为template
只能使用字符串常量,而不是值/变量作为参数(对吗?)
在模板上强制使用一长串if
语句的原因似乎是这种编程风格被认为是“逻辑”,应该从模板中取出,至少在语言的“标准”级别上。Go 程序员不应该认为模板引擎(=表示层)中有任何内在的“逻辑”。当然,我不能讨论什么被认为是逻辑,什么不是(if
允许测试特定值是否相等并根据这些值执行不同块的语句对我来说肯定是“逻辑”,但是显然不适合 Go 开发人员)。
几年前也有人问过类似的问题,但对 OP 来说,答案从来都不是很令人满意。基本上,据我了解,有几种选择:
- 定义一个新函数,扩展模板代码,最终创建等效的 switch 语句;这至少可以节省一些
{{ if ... end }}
构造,但是,对我来说,它仍然缺乏单行的简单性和可读性。 - 破解(或者,更确切地说,扩展......)整个
html/template
包以更改模板语法,据称这是由 @Intermernet 在四年前完成的。当然,这是一个有效的练习,但这意味着摆脱标准的 Go 库。如果这是选择,那么那里有很多用于 Go 的模板引擎;我只是不愿意开始使用其中一个,几年后发现它已经过时了,因为作者已经放弃了这个项目。使用不会发生的标准库(至少在 Google 存在并且Ken Thompson还活着的时候)。 - 对 Go 端使用的子模板进行所有处理。这自然是可行的,但是(恕我直言)它会导致代码的可读性大大降低。当然,我知道 Go 程序员之间的意识形态之争,在那些热衷于编写“惯用”(但难以理解)代码的人与许多其他有不同编写 Go 代码方式的派系之间。就我个人而言,我坚持最小惊喜和KISS原则——我希望我自己的代码即使在我写完十年后也能被理解:)
模板语法是否朝着允许我所描述的方向发展(我很不幸没有找到任何工作示例),还是我仍然坚持复杂化 Go 代码,或者使用不同的非标准 Go 模板引擎完成这个简单的任务?
提前感谢大家的任何见解。我仍然在祈祷,希望我只是 Go 模板语法的新手,并且它实际上允许我想要的,我只需要添加一些更尴尬的符号以允许template
关键字接受变量而不是一个字符串常量,到目前为止,我一直没有找到它:-)