【发布时间】:2017-12-07 21:24:36
【问题描述】:
我有一个函数,它的参数类型为interface{}。这个参数代表我的模板数据。所以在每个页面上它存储不同的数据类型(主要是结构)。我想在这个参数的数据上附加一些数据,但它是interface{} 类型,我做不到。
这是我尝试过的:
func LoadTemplate(templateData interface) {
appendCustomData(&templateData)
... //other functionality that is not relevant
}
func appendCustomData(dst interface{}) {
// ValueOf to enter reflect-land
dstPtrValue := reflect.ValueOf(dst)
// need the type to create a value
dstPtrType := dstPtrValue.Type()
// *T -> T, crashes if not a ptr
dstType := dstPtrType.Elem()
// the *dst in *dst = zero
dstValue := reflect.Indirect(dstPtrValue)
// the zero in *dst = zero
zeroValue := reflect.Zero(dstType)
// the = in *dst = 0
v := reflect.ValueOf(dst).Elem().Elem().FieldByName("HeaderCSS")
if v.IsValid() {
v = reflect.ValueOf("new header css value")
}
reflect.ValueOf(dst).Elem().Elem().FieldByName("HeaderCSS").Set(reflect.ValueOf(v))
//dstValue.Set(zeroValue)
fmt.Println("new dstValue: ", dstValue)
}
我可以成功获取"HeaderCSS" 值。但我不能用另一个值替换它。我做错了什么?
我的模板数据如下所示:
我有一个通用结构:
type TemplateData struct {
FooterJS template.HTML
HeaderJS template.HTML
HeaderCSS template.HTML
//and some more
}
我还有另外一个结构体,比如:
type pageStruct struct {
TemplateData //extends the previous struct
Form template.HTML
// and some other maps/string
}
我将第二个结构作为 templateData 参数发送。
现在我收到此错误:
“reflect.Value.Set using unaddressable value”在以下行:reflect.ValueOf(dst).Elem().Elem().FieldByName("HeaderCSS").Set(reflect.ValueOf(v))
上面的代码灵感来自这个答案:https://stackoverflow.com/a/26824071/1564840
我希望能够从此界面附加/编辑值。知道我该怎么做吗?谢谢。
【问题讨论】:
-
似乎您知道实际类型:只需对该类型键入 assert 并执行该类型支持的任何操作。如果不是:您必须显示完整的代码。 BTW:去掉空的
interface{},你的代码会更简单。 -
我不能只删除接口{},因为每个页面上的参数类型都会不同。 interface{} 是允许我接受各种参数的选项。
-
这已经得到了很好的回答,但我想建议您也许应该添加一个
SetHeaderCSS方法并传入一个指定该方法的HeaderCSSSetter接口。这将通过简单的更改消除所有反射,从而为您提供更好的性能、更好的可读性和编译时类型安全。 -
好主意。谢谢!
标签: pointers go interface go-templates go-interface