游乐场链接:http://play.golang.org/p/Ebf5AuJlcP
type Foo interface {}
type Bar interface {
ThisIsABar()
}
// Person implements both Foo and Bar
type Person struct {
Name string
}
func (p Person) ThisIsABar() {}
type FooContext struct {
Something Foo
}
type BarContext struct {
Something Bar
}
func main() {
t := template.Must(template.New("test").Parse("{{ .Something.Name }}\n"))
// This works fine.
if err := t.Execute(os.Stdout, FooContext{Person{"Timmy"}}); err != nil {
fmt.Printf("Error: %s\n", err)
}
// With BarContext, containing the exact same Person but wrapped in a
// different interface, it errors out.
if err := t.Execute(os.Stdout, BarContext{Person{"Timmy"}}); err != nil {
fmt.Printf("Error: %s\n", err)
}
}
当我渲染一个包含text/template
的模板(通过{{ .Something.Name }}
包)时,我可以通过不包含任何方法的接口Foo
,并且它可以正常工作。但是,如果我通过界面Bar
代替,我得到:
executing "test" at <.Something.Name>: can't evaluate field Name in type main.Bar
为什么界面上存在不相关的方法,甚至不使用,会影响模板的渲染?
答案 0 :(得分:6)
text / template是特殊的外壳接口{},所以被调用的函数可以有返回类型接口{}等。向接口添加方法意味着检测不再触发。
http://golang.org/src/pkg/text/template/exec.go#L323
323 for _, cmd := range pipe.Cmds {
324 value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg.
325 // If the object has type interface{}, dig down one level to the thing inside.
326 if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 {
327 value = reflect.ValueOf(value.Interface()) // lovely!
328 }
329 }
BarContext.Something是一个Bar(一个接口)。条形码没有字段名称。如果要在那里使用接口,则需要通过作为接口一部分的方法提供数据。