使用golang html/template
(与text/template
相同的行为)。如果我有一个具有接口类型的成员的结构,我无法访问基础类型的成员(特别是尝试访问实现接口InnerInterface
的结构上的字段,但是通过{{1返回接口类型,而不是结构类型)。
http://play.golang.org/p/ZH8wSK83oM
InnerInterface
将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{}
?
答案 0 :(得分:4)
你说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
}
调用此方法以获得反射值的最深值。 假设你有一个指针指针上的指针,这个函数将返回 最后一个。接口值也是如此。问题的关键在于 接口值有多于0个方法,间接停在那里。完全是 你正在描述的行为。
由于这似乎是预期的行为,您可以做的是定义Title() string
在你的界面中的方法,让它返回字符串。