界面中不相关方法的存在会破坏文本/模板吗?

时间:2013-10-30 21:31:33

标签: interface go go-templates

游乐场链接: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

为什么界面上存在不相关的方法,甚至不使用,会影响模板的渲染?

1 个答案:

答案 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(一个接口)。条形码没有字段名称。如果要在那里使用接口,则需要通过作为接口一部分的方法提供数据。