go的`Template.Execute`方法如何读取匿名结构体参数的字段?

huangapple go评论117阅读模式
英文:

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

问题

在使用Go编码时,使用html.template包,会调用template.Execute方法。
我有一个问题,它如何读取参数中匿名结构体的字段。
我阅读了源代码,但是不太明白。我没有主意。

在上述代码中,Template结构体定义了一个text字段,类型为*template.Template。

escape方法用于转义所有关联的模板。在执行模板转义之前,会先对nameSpace进行加锁,然后在函数结束时解锁。如果escapeErr为nil,则表示转义成功;如果Tree为nil,则表示模板不完整或为空;否则,会调用escapeTemplate函数对模板进行转义。

Execute方法用于将解析后的模板应用于指定的数据对象,并将输出写入wr。如果执行模板或写入输出时发生错误,执行将停止,但部分结果可能已经写入输出写入器。模板可以安全地并行执行。

根据GoDoc的示例,可以像这样使用Execute方法:

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

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

英文:

In coding with Go, with html.template package, template.Execute is called.<br>
I have a question, how could it read the field of anonymous structure of its parameter.<br>
I read the source code, but it doesn't make sense. I don't have an idea.

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

  1. type Template struct {
  2. ...
  3. text *template.Template
  4. ...
  5. }
  6. // escape escapes all associated templates.
  7. func (t *Template) escape() error {
  8. t.nameSpace.mu.Lock()
  9. defer t.nameSpace.mu.Unlock()
  10. if t.escapeErr == nil {
  11. if t.Tree == nil {
  12. return fmt.Errorf(&quot;template: %q is an incomplete or empty template%s&quot;, t.Name(), t.text.DefinedTemplates())
  13. }
  14. if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil {
  15. return err
  16. }
  17. } else if t.escapeErr != escapeOK {
  18. return t.escapeErr
  19. }
  20. return nil
  21. }
  22. // Execute applies a parsed template to the specified data object,
  23. // writing the output to wr.
  24. // If an error occurs executing the template or writing its output,
  25. // execution stops, but partial results may already have been written to
  26. // the output writer.
  27. // A template may be executed safely in parallel.
  28. func (t *Template) Execute(wr io.Writer, data interface{}) error {
  29. if err := t.escape(); err != nil {
  30. return err
  31. }
  32. return t.text.Execute(wr, data)
  33. }

GoDoc demonstrates its usage, calling Execute with its interface{} paramter like this;

  1. data := struct {
  2. Title string
  3. Items []string
  4. }{
  5. Title: &quot;My another page&quot;,
  6. Items: []string{},
  7. }
  8. err = t.Execute(os.Stdout, data)

答案1

得分: 1

如果你看一下Execute函数的return语句,它调用了text/template包中的t.text.Execute函数:

  1. func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
  2. defer errRecover(&err)
  3. value := reflect.ValueOf(data)
  4. state := &state{
  5. tmpl: t,
  6. wr: wr,
  7. vars: []variable{{"$", value}},
  8. }
  9. if t.Tree == nil || t.Root == nil {
  10. state.errorf("%q is an incomplete or empty template%s", t.Name(), t.DefinedTemplates())
  11. }
  12. state.walk(value, t.Root)
  13. return
  14. }

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

这里有一个简单的示例来说明正在发生的事情:http://play.golang.org/p/ih1Ei33NsO

英文:

If you look at the return of Execute it calls t.text.Execute which is calling this function from the text/template package:

  1. 132 func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
  2. 133 defer errRecover(&amp;err)
  3. 134 value := reflect.ValueOf(data)
  4. 135 state := &amp;state{
  5. 136 tmpl: t,
  6. 137 wr: wr,
  7. 138 vars: []variable{{&quot;$&quot;, value}},
  8. 139 }
  9. 140 if t.Tree == nil || t.Root == nil {
  10. 141 state.errorf(&quot;%q is an incomplete or empty template%s&quot;, t.Name(), t.DefinedTemplates())
  11. 142 }
  12. 143 state.walk(value, t.Root)
  13. 144 return
  14. 145 }

So it will use the reflect package to parse the variables into the template.

Here's a little example of whats happening: http://play.golang.org/p/ih1Ei33NsO

huangapple
  • 本文由 发表于 2016年1月9日 11:55:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/34689509.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定