使用 golang html/template
(与 text/template
行为相同)。如果我有一个包含接口(interface)类型成员的结构,我无法访问基础类型的成员(特别是试图访问实现接口(interface) InnerInterface
但通过返回的结构上的字段InnerInterface
接口(interface)类型,不是结构类型)。
http://play.golang.org/p/ZH8wSK83oM
package main
import "fmt"
import "os"
import "html/template"
type InnerInterface interface{ InnerSomeMethod() }
type MyInnerStruct struct { Title string }
func (mis MyInnerStruct)InnerSomeMethod() { fmt.Println("Just to show we're satisfying the interface") }
type MyOuterStruct struct { Inner InnerInterface }
func main() {
fmt.Println("Starting")
arg := MyOuterStruct{Inner:MyInnerStruct{Title:"test1"}}
err := template.Must(template.New("testtmpl").Parse("{{.Inner.Title}}")).Execute(os.Stdout, arg)
if err != nil { panic(err) }
}
更改:type MyOuterStruct struct { Inner InnerInterface }
为完全通用的接口(interface),即 type MyOuterStruct struct { Inner interface{} }
使其正确呈现。这让我相信 interface{}
是由渲染引擎特殊处理的。
每当我希望能够像这样动态评估字段时,是否有比使用 interface{}
更好的方法来做到这一点?
最佳答案
您说 interface{}
以不同方式处理渲染是正确的
引擎。只有 interface{}
值被解压,没有设置方法的接口(interface)值。
我想这背后的原因是,如果你有一个接口(interface)类型,你专门将类型限制为方法集。因此,您不希望模板引擎尝试访问可能位于该接口(interface)后面的成员。
“问题”是由函数 indirect
in exec.go
引起的:
func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
if v.IsNil() {
return v, true
}
if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
break
}
}
return v, false
}
调用此方法以获取反射值的最深值。 假设你在一个指针上有一个指针,这个函数将返回 最后一个。接口(interface)值也是如此。关键是一旦 接口(interface)值有超过 0 个方法,间接到此为止。正是 您所描述的行为。
由于这似乎是预期的行为,您可以做的是定义一个 Title() string
方法并让它返回字符串。
关于interface - 模板不会将接口(interface)类型的字段评估为基础类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19554209/