go 'Template.Execute' 是如何读取其匿名结构的参数字段的?

How does the go 'Template.Execute' read its prameter's fields of anonymous strcuture?

在使用 Go 编码时,使用 html.template 包,调用 template.Execute。
我有一个问题,它如何读取其参数的匿名结构字段。
看了源码,没看懂。我不知道。

/usr/local/go/src/html/template/tempalte.go L.78

type Template struct {
    ...
    text *template.Template
    ...
}

// escape escapes all associated templates.
func (t *Template) escape() error {
    t.nameSpace.mu.Lock()
    defer t.nameSpace.mu.Unlock()
    if t.escapeErr == nil {
        if t.Tree == nil {
            return fmt.Errorf("template: %q is an incomplete or empty template%s", t.Name(), t.text.DefinedTemplates())
        }
        if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil {
            return err 
        }
    } else if t.escapeErr != escapeOK {
        return t.escapeErr
    }   
    return nil 
}

// Execute applies a parsed template to the specified data object,
// writing the output to wr.
// If an error occurs executing the template or writing its output,
// execution stops, but partial results may already have been written to
// the output writer.
// A template may be executed safely in parallel.
func (t *Template) Execute(wr io.Writer, data interface{}) error {
    if err := t.escape(); err != nil {
        return err 
    }   
    return t.text.Execute(wr, data)
}

GoDoc 演示了它的用法,调用 Execute 的接口{}参数是这样的;

data := struct {
    Title string
    Items []string
}{
    Title: "My another page",
    Items: []string{},
}


err = t.Execute(os.Stdout, data)

如果您查看 Executereturn,它会调用 t.text.Execute,它会从 text/template 包中调用此函数:

   132  func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
   133      defer errRecover(&err)
   134      value := reflect.ValueOf(data)
   135      state := &state{
   136          tmpl: t,
   137          wr:   wr,
   138          vars: []variable{{"$", value}},
   139      }
   140      if t.Tree == nil || t.Root == nil {
   141          state.errorf("%q is an incomplete or empty template%s", t.Name(), t.DefinedTemplates())
   142      }
   143      state.walk(value, t.Root)
   144      return
   145  }

因此它将使用 reflect 包将变量解析到模板中。

这里有一个小例子:http://play.golang.org/p/ih1Ei33NsO