我正在尝试构建一个易于使用的模板系统。基本上我只想创建一个包含不同变量(字符串)的切片,然后遍历切片并将标记{{}}
替换为实际值。因此,如果变量“name
”为onevar
,它将在{{onevar}}
的模板中查找,并将其替换为变量的实际值。
问题:如何获取变量名称?基本上是源代码中的内容。可能吗 ?我尝试过反思,但似乎无法做到正确。见下文
onevar := "something"
other := "something else"
var msg string
sa := []string{onevar, other}
for _, v := range sa {
vName := reflect.TypeOf(v).Name()
vName = fmt.Sprintf("{{%s}}", vName)
msg = strings.Replace(msg, vName, v, -1)
}
答案 0 :(得分:2)
你不能做这样的事情。 slive 不包含变量但是值,因此您无法获取其名称。只需使用地图。
答案 1 :(得分:1)
而不是使用变量名称,您可以使用带有(字符串转换的)指针的切片来实现您的原始目标:
package main
import "fmt"
import "unsafe"
import "strconv"
func castStr(v *string) string {
return fmt.Sprint(uintptr(unsafe.Pointer(v)))
}
func uncastStr(s string) string {
p, _ := strconv.ParseInt(s, 10, 64)
return *((*string)(unsafe.Pointer(uintptr(p))))
}
func main() {
onevar := "something"
other := "something else"
sa := []string{castStr(&onevar), castStr(&other)}
for _, v := range sa {
fmt.Printf("{{%s}}\n", v)
fmt.Printf("%v\n", uncastStr(v))
}
//for _, v := range sa {
// vName := fmt.Sprintf("{{%s}}", v)
// msg = strings.Replace(msg, vName, uncastStr(v) -1)
//}
}
(在这里看不到使用不安全的问题,因为任何强制转换都不是基于不受控制的内容而且不安全.Pointer仅用于阅读。 注意!:请记住,指针值可能会因程序运行而异。因此,在程序的第二次运行中替换模板{{xxx}}可能会失败。此外:该场景(第二次运行)可能“不安全”,因为可能会评估不相关的内存。)
答案 2 :(得分:0)
这是个好问题。我需要相同的解决方案,但对于vars(我认为这不可能)-对于结构。您可以尝试为此使用结构。
package main
import (
"fmt"
"reflect"
)
type Some struct {
Foo bool
A string
Bar int
B string
}
func (structPoint *Some) GetFieldName(fieldPinter interface{}) (name string) {
val := reflect.ValueOf(structPoint).Elem()
val2 := reflect.ValueOf(fieldPinter).Elem()
for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i)
if valueField.Addr().Interface() == val2.Addr().Interface() {
return val.Type().Field(i).Name
}
}
return
}
func main() {
a := Some{}
fieldName := a.GetFieldName(&a.Foo)
fmt.Println(fieldName)
fieldName = a.GetFieldName(&a.Bar)
fmt.Println(fieldName)
//Foo
//Bar
}