在go模板中通过字段名动态访问结构值
Dynamically access struct value by field name in go template
有没有办法在 go 模板中通过字段名动态访问结构值?
对于此代码 (https://play.golang.org/p/1B1sz0gnbAi):
package main
import (
"fmt"
"os"
"text/template"
)
type Context struct {
Key string
}
func main() {
var context = Context{Key: "value"}
// Success
var text = `{{ .Key }}`
t := template.Must(template.New("success").Parse(text))
_ = t.Execute(os.Stdout, context)
fmt.Println("")
// Fail
text = `{{- $key := "Key" }}{{ .$key}}`
t = template.Must(template.New("fail").Parse(text))
err := t.Execute(os.Stdout, context)
if err != nil {
fmt.Println("executing template:", err)
}
}
我得到这个输出:
value
panic: template: fail:1: unexpected bad character U+0024 '$' in command
goroutine 1 [running]:
text/template.Must(...)
/usr/local/go-faketime/src/text/template/helper.go:23
main.main()
/tmp/sandbox897259471/prog.go:26 +0x46b
我知道如何为地图执行此操作,我只想使用索引函数。但这对结构不起作用,而且我没有灵活性来更改作为上下文传入的基础类型。
有什么想法吗?
即使在常规的 golang 代码中,按名称访问结构字段也需要反射,因此在模板中也不是那么容易。没有允许它的 built-in 函数,我也不知道有任何库提供这样的函数。您可以做的是自己实现该功能。一个非常基本的实现如下:
package main
import (
"fmt"
"os"
"text/template"
"reflect"
)
type Context struct {
Key string
}
func FieldByName(c Context, field string) string {
ref := reflect.ValueOf(c)
f := reflect.Indirect(ref).FieldByName(field)
return string(f.String())
}
func main() {
context := Context{Key: "value"}
text := `{{- $key := "Key" }}{{ fieldByName . $key}}`
// Custom function map
funcMap := template.FuncMap{
"fieldByName": FieldByName,
}
// Add custom functions using Funcs(funcMap)
t := template.Must(template.New("fail").Funcs(funcMap).Parse(text))
err := t.Execute(os.Stdout, context)
if err != nil {
fmt.Println("executing template:", err)
}
}
上查看
有没有办法在 go 模板中通过字段名动态访问结构值?
对于此代码 (https://play.golang.org/p/1B1sz0gnbAi):
package main
import (
"fmt"
"os"
"text/template"
)
type Context struct {
Key string
}
func main() {
var context = Context{Key: "value"}
// Success
var text = `{{ .Key }}`
t := template.Must(template.New("success").Parse(text))
_ = t.Execute(os.Stdout, context)
fmt.Println("")
// Fail
text = `{{- $key := "Key" }}{{ .$key}}`
t = template.Must(template.New("fail").Parse(text))
err := t.Execute(os.Stdout, context)
if err != nil {
fmt.Println("executing template:", err)
}
}
我得到这个输出:
value
panic: template: fail:1: unexpected bad character U+0024 '$' in command
goroutine 1 [running]:
text/template.Must(...)
/usr/local/go-faketime/src/text/template/helper.go:23
main.main()
/tmp/sandbox897259471/prog.go:26 +0x46b
我知道如何为地图执行此操作,我只想使用索引函数。但这对结构不起作用,而且我没有灵活性来更改作为上下文传入的基础类型。
有什么想法吗?
即使在常规的 golang 代码中,按名称访问结构字段也需要反射,因此在模板中也不是那么容易。没有允许它的 built-in 函数,我也不知道有任何库提供这样的函数。您可以做的是自己实现该功能。一个非常基本的实现如下:
package main
import (
"fmt"
"os"
"text/template"
"reflect"
)
type Context struct {
Key string
}
func FieldByName(c Context, field string) string {
ref := reflect.ValueOf(c)
f := reflect.Indirect(ref).FieldByName(field)
return string(f.String())
}
func main() {
context := Context{Key: "value"}
text := `{{- $key := "Key" }}{{ fieldByName . $key}}`
// Custom function map
funcMap := template.FuncMap{
"fieldByName": FieldByName,
}
// Add custom functions using Funcs(funcMap)
t := template.Must(template.New("fail").Funcs(funcMap).Parse(text))
err := t.Execute(os.Stdout, context)
if err != nil {
fmt.Println("executing template:", err)
}
}
上查看