Golang文本模板中如何实现安全导航支持
Golang文本模板中如何实现安全导航支持
我了解到安全导航操作符提案已被否决,但有没有可能在text/template包中支持?.作为操作符呢?
例如,在这个PR中,我添加了使用GitHub CLI用于内置命令输出的相同格式化程序来打印表格的支持。但很多时候,来自GraphQL查询的某些字段是嵌套的,我需要导航到例如.status.message,而.status可能为nil。我可以使用{{if}}动作以及模板其余部分的近似重复内容,但1)这会变得非常笨拙,2)如果有人想要深入多个嵌套节点,情况会更加笨拙。
考虑到text/template已经是它自己的一种特殊小语言,至少提议(甚至可能实现)对安全导航操作符的支持是否可以接受呢?
更多关于Golang文本模板中如何实现安全导航支持的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang文本模板中如何实现安全导航支持的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go的text/template中,目前确实没有内置的安全导航操作符(如?.)。不过,你可以通过自定义函数来实现类似的功能。以下是一个示例,展示如何注册一个自定义函数来安全地访问嵌套字段:
package main
import (
"os"
"text/template"
"reflect"
)
// safeGet 安全获取嵌套字段的值,如果路径中任何部分为nil,则返回nil
func safeGet(data interface{}, path ...string) interface{} {
v := reflect.ValueOf(data)
for _, key := range path {
if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
if v.IsNil() {
return nil
}
v = v.Elem()
}
if v.Kind() != reflect.Map {
return nil
}
v = v.MapIndex(reflect.ValueOf(key))
if !v.IsValid() {
return nil
}
}
return v.Interface()
}
func main() {
// 示例数据
data := map[string]interface{}{
"status": map[string]interface{}{
"message": "Hello, World!",
},
}
// 创建模板并注册自定义函数
tmpl := template.New("test").Funcs(template.FuncMap{
"get": safeGet,
})
// 解析模板
tmpl, err := tmpl.Parse(`
{{ $msg := get . "status" "message" }}
{{ if $msg }}
Message: {{ $msg }}
{{ else }}
No message available.
{{ end }}
`)
if err != nil {
panic(err)
}
// 执行模板
err = tmpl.Execute(os.Stdout, data)
if err != nil {
panic(err)
}
}
输出:
Message: Hello, World!
如果status为nil,例如:
data := map[string]interface{}{
"status": nil,
}
输出:
No message available.
这种方法避免了在模板中重复使用{{if}}动作,并允许你安全地访问嵌套字段。虽然这不是一个真正的操作符,但它在功能上提供了类似的安全导航能力。

