模板不会评估作为基础类型的接口类型的字段

时间:2013-10-23 23:30:20

标签: interface struct go field

使用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{}

1 个答案:

答案 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 在你的界面中的方法,让它返回字符串。