Golang模板中如何使用包含连字符的map键
Golang模板中如何使用包含连字符的map键
在使用包含连字符(-)的键(例如 {{.vars.X-test}})时,模板会崩溃。之前使用基础模板一直没问题。有人遇到过这个问题并知道解决方案吗?
代码:
- 数据结构
type Stack struct {
StepResult map[string]interface{}
}
vars := make(map[string]string, paramLen)
stack.StepResult["vars"] = vars
vars["X-test"] = "abc"
- 模板函数
func (stack Stack) QueryFromStepResult(template string) string {
tmpl, _ := template.New("key").Parse(template)
buf := new(bytes.Buffer)
tmpl.Execute(buf, stack.StepResult)
return buf.String()
}
- 使用
{{.vars.X-test}}调用函数时崩溃
runtime error: invalid memory address or nil pointer dereference
/usr/bin/go/src/text/template/exec.go:164 (0x9c1fba)
errRecover: panic(e)
/usr/bin/go/src/runtime/panic.go:838 (0x6366a6)
gopanic: done = runOpenDeferFrame(gp, d)
/usr/bin/go/src/runtime/panic.go:220 (0x64c835)
panicmem: panic(memoryError)
/usr/bin/go/src/runtime/signal_unix.go:818 (0x64c805)
sigpanic: panicmem()
/usr/bin/go/src/text/template/exec.go:215 (0x9c23ec)
(*Template).execute: if t.Tree == nil || t.Root == nil {
/usr/bin/go/src/text/template/exec.go:201 (0xb0a1d4)
(*Template).Execute: return t.execute(wr, data)
/code/go/tms-go-apihub/broker/hub/stack.go:26 (0xb0a0a7)
Stack.QueryFromStepResult: tmpl.Execute(buf, stack.StepResult)
更多关于Golang模板中如何使用包含连字符的map键的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
你好 @wangbin,
赋值操作会复制被赋的值,因此向 vars 添加 abc 不会影响 StepResult["vars"] 中的值:
stack.StepResult[“vars”] = vars
vars[“X-test”] = “abc”
尝试调换对 vars 和 StepResult 赋值的顺序:
vars["X-test"] = "abc"
stack.StepResult["vars"] = vars
另外有个小建议:发布代码时请使用代码围栏,像这样:
vars["X-test"] = "abc"
stack.StepResult["vars"] = vars
这样可以保留缩进、添加语法高亮,使你的代码更易于阅读。
更多关于Golang模板中如何使用包含连字符的map键的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go模板中访问包含连字符的map键需要使用index函数。连字符在模板语法中有特殊含义(减法操作),所以不能直接使用点号访问。
解决方案:
// 在模板中使用index函数访问带连字符的键
templateStr := `{{index .vars "X-test"}}`
// 或者如果有多层嵌套
templateStr := `{{index .vars "X-test"}}`
// 完整的示例代码
func (stack Stack) QueryFromStepResult(template string) string {
tmpl, err := template.New("key").Parse(template)
if err != nil {
// 处理错误
return ""
}
buf := new(bytes.Buffer)
err = tmpl.Execute(buf, stack.StepResult)
if err != nil {
// 处理错误
return ""
}
return buf.String()
}
// 使用示例
stack := Stack{
StepResult: map[string]interface{}{
"vars": map[string]string{
"X-test": "abc",
"Y-test": "def",
},
},
}
// 正确的调用方式
result := stack.QueryFromStepResult(`{{index .vars "X-test"}}`)
// result 将是 "abc"
// 也可以访问其他带特殊字符的键
result2 := stack.QueryFromStepResult(`{{index .vars "Y-test"}}`)
// result2 将是 "def"
// 如果需要处理可能不存在的键
result3 := stack.QueryFromStepResult(`{{if index .vars "Z-test"}}{{index .vars "Z-test"}}{{else}}default{{end}}`)
// result3 将是 "default"
如果需要在同一个模板中多次访问同一个键,可以这样写:
// 使用with语句简化
templateStr := `{{with index .vars "X-test"}}{{.}}{{else}}not found{{end}}`
// 或者使用变量
templateStr := `{{$value := index .vars "X-test"}}The value is: {{$value}}`
对于包含其他特殊字符(如下划线、点号等)的键,同样需要使用index函数:
// 包含点号的键
vars["test.key"] = "value123"
templateStr := `{{index .vars "test.key"}}`
// 包含下划线的键(可以直接访问,但index也适用)
vars["test_key"] = "value456"
templateStr1 := `{{.vars.test_key}}` // 这样可以
templateStr2 := `{{index .vars "test_key"}}` // 这样也可以

