Golang Template 开发网页时遇到一个模版内变量命名的问题。
问题
多个不同页面需要使用同一个子模版,比如推荐产品列表这个子模版,需要在产品列表页、首页、404页面、搜索页面等多个页面使用该子模版。
子模版目前是这样定义的, product_cards.html:
{{ range .Items }}
<div class="product-card">
<a href="{{ .URL }}" class="block">
<h3 class="product-name">{{ .Name }}</h3>
</a>
</div>
{{ else }}
<p class="text-gray">No products found.</p>
{{ end }}
其他页面引用子模版:
{{ template "product_cards.html" . }}
看起来没啥问题,但是当多个页面引用同一个子模版时,就会出现变量名歧义的问题。 例如,产品页使用 Items 没啥问题,很好理解,Items 是产品列表。 但是在首页使用这个子模版时,Items 这个名字就不太合适了,因为首页还有其他的展示区域,Items 这个名字就不够具体。
golang template 文档
https://pkg.go.dev/text/template
官方文档,真的一言难尽,又枯燥又抽象。我也没有找到什么具体的例子来说明这个问题。
Google 了半天,也没有找到类似的问题讨论。 因为我也不知道该怎么描述这个问题。。。
{{ template "product_cards.html" . }}
这种语法到底应该叫子模版,还是嵌套模版,还是其他什么名字?我知道 PHP Laravel 里叫 include 语法。 但是 golang 这里 template 关键词跟功能名称一样就更没法描述了 😅
{{template "name"}}
The template with the specified name is executed with nil data.
{{template "name" pipeline}}
The template with the specified name is executed with dot set
to the value of the pipeline.
今天抽时间把这个官方文档再读一遍,整理出来看不懂的概念,例如 pipeline,问问 AI 比较好。
最后还是得靠 DeepSeek 才能搞定。
子模版内部重新赋值
DeepSeek 给出的方案是:
父模板中直接使用对应的变量名传递给子模板,例如:
{{ template "product_cards.html" .Products }}
子模版内部重新赋值一个变量名
{{ $items := . }}
{{ range $index, $item := $items }}
<div>{{ $item.Name }}</div>
{{ end }}
或者
{{ $items := . }}
{{ range $items }}
<div>{{ .Name }}</div>
{{ end }}
感觉还是第一种方式可读性更好一些。到处是 . 很不好理解。
子模版中的 . 代表父模板传递过来的数据,可以直接赋值给一个新的变量名 $items,然后在子模版内部使用 $items 来进行遍历和操作。
到此,问题完美解决。
golang template 中的变量
https://docs.gofiber.io/template/html/TEMPLATES_CHEATSHEET/#template-variables
gofiber 的文档倒是比 go 官方文档好一些,里面有专门示例说明:
总结一下,就是:
golang 传递给模板的数据,是通过 . 来访问的:
- 如果传递的是 map,则可以通过 .Key 来访问对应的值
- 如果传递的是整形/字符串等基本类型,则直接使用 .
- 如果是父模板传递给子模板的数据,则同样使用 . 来处理
同时,可以在模板内部定义变量,使用
{{$number := .}}
<h1> It is day number {{$number}} of the month </h1>
语法来定义变量,然后通过 $xxx 来访问变量的值。
有必要单独整理一个文档来项目列举各种使用场景。
关于作者 🌱
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式