使用golang html/template(与的行为相同text/template)。如果我具有一个成员类型为接口类型的结构,则无法访问基础类型的成员(特别是尝试访问实现接口InnerInterface但通过InnerInterface接口类型而非结构类型返回的结构上的字段) 。
html/template
text/template
InnerInterface
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 }为完全通用的接口,即使type MyOuterStruct struct { Inner interface{} }其正确呈现。这使我相信interface{}渲染引擎对它进行了特殊处理。
type MyOuterStruct struct { Inner InnerInterface }
type MyOuterStruct struct { Inner interface{} }
interface{}
有什么比interface{}我每时每刻想要能够动态评估字段的方法更好的方法呢?
您的说法是正确的,interface{}渲染引擎对此进行了不同的处理。仅interface{}解包了值,没有解包了设置方法的接口值。我想这背后的原因是,如果您有接口类型,则可以将类型专门限制为方法集。因此,您不希望模板引擎尝试访问该接口后面的成员。
“问题”是由功能引起indirect的exec.go:
indirect
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 }
调用此方法以获得反射值的最深值。假设您在一个指针上有一个指针,则该函数将返回其中的最后一个。接口值也是如此。问题的关键是,只要接口值具有多个0方法,则间接寻址将在此处停止。正是您所描述的行为。
因为这似乎是预期的行为,所以您可以做的是Title() string 在接口中定义一个方法,并让它返回字符串。
Title() string