
go 模板不支持直接使用 `arr[1]` 语法,但可通过内置函数 `index` 获取切片或数组指定位置的元素,适用于服务返回多值场景(如 `service "mongodb"` 返回实例列表时提取第二个)。
在 Go 的 text/template 包中,模板语言本身不提供方括号索引操作符(如 {{ .Items[1] }}),因此无法像 Go 代码中那样直接写 arr[1]。但标准库提供了安全、通用的内置函数 index,专用于对 map、slice 或 array 进行链式索引访问。
✅ 正确用法:使用 index 函数
语法为:
{{ index }} 其中
以你的原始需求为例——调用 {{ service "mongodb" }} 返回一个含 3 个元素的切片,需取第二个元素(索引为 1),应改写为:
test start
{{ index (service "mongodb") 1 }}
test end⚠️ 注意:index 要求第一个参数必须是可索引类型(slice/array/map),且索引值不能越界,否则模板执行会 panic。生产环境中建议确保数据长度足够,或结合 len 和 if 做防护(见下文)。
? 完整可运行示例
以下是一个最小化验证程序,模拟 service 函数返回 MongoDB 实例切片:
package main
import (
"log"
"os"
"text/template"
)
// 模拟服务发现函数:返回 3 个 mock 实例地址
func service(name string) []string {
switch name {
case "mongodb":
return []string{"mongodb-0.example.com", "mongodb-1.example.com", "mongodb-2.example.com"}
default:
return []string{}
}
}
func main() {
funcMap := template.FuncMap{
"service": service,
}
const tmplText = `test start
{{ index (service "mongodb") 1 }}
test end`
t, err := template.New("access").Funcs(funcMap).Parse(tmplText)
if err != nil {
log.Fatal("parse error:", err)
}
if err := t.Execute(os.Stdout, nil); err != nil {
log.Fatal("execute error:", err)
}
}输出:
test start mongodb-1.example.com test end
? 安全增强:避免索引越界
为防止因切片长度不足导致 panic,推荐先判断长度:
{{ with $svc := (service "mongodb") }}
{{ if ge (len $svc) 2 }}
{{ index $svc 1 }}
{{ else }}
N/A
{{ end }}
{{ else }}
No service found
{{ end }}这里用到了 len(获取长度)、ge(大于等于)和 with(作用域绑定)等常用模板函数,显著提升鲁棒性。
✅ 总结
- ✅ 使用 {{ index (func ...) N }} 是访问模板中任意 slice/array 元素的标准且唯一推荐方式;
- ❌ 不要尝试 {{ (func ...)[1] }} —— Go 模板不支持该语法;
- ? 结合 len + if 可实现安全索引,适合生产环境;
- ? 所有内置函数文档详见 pkg.go.dev/text/template。
掌握 index 的用法,不仅能解决单层切片取值,还可延伸至嵌套结构(如 {{ index (index .Data "users") 0 }}),是编写健壮 Go 模板的关键基础能力。









