Golang模板中如何使用包含连字符的map键

Golang模板中如何使用包含连字符的map键 在使用包含连字符(-)的键(例如 {{.vars.X-test}})时,模板会崩溃。之前使用基础模板一直没问题。有人遇到过这个问题并知道解决方案吗?

代码:

  1. 数据结构
type Stack struct {
    StepResult map[string]interface{}
}
vars := make(map[string]string, paramLen)
stack.StepResult["vars"] = vars
vars["X-test"] = "abc"
  1. 模板函数
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()
}
  1. 使用 {{.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”

尝试调换对 varsStepResult 赋值的顺序:

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"}}`  // 这样也可以
回到顶部