Go模板函数

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

Go template function

问题

它注意到了使用FuncsFuncMap时Go模板的一个奇怪的问题。以下代码按预期工作:

buffer := bytes.NewBufferString("")

funcMap := template.FuncMap{
    "label": strings.Title,
}

t, _ := template.New("alex").Funcs(funcMap).Parse("{{label \"alex\"}}")

t.Execute(buffer, "")

return string(buffer.Bytes()) // => "Alex"

但是当我尝试将模板放在一个文件中时,它不起作用(Execute()显示:“alex是一个不完整或空的模板”):

t, _ := template.New("alex").Funcs(funcMap).ParseFiles("template.html")

使用template.html:

{{label "alex"}}

有什么想法为什么会这样?这是一个bug吗?有没有更简单的方法在模板中使用方法/函数?

英文:

It noticed a weird thing with Go templates when I try to use Funcs and FuncMap. The following code works as expected:

buffer := bytes.NewBufferString("")

funcMap := template.FuncMap{
    "label": strings.Title,
}

t, _ := template.New("alex").Funcs(funcMap).Parse("{{label \"alex\"}}") 

t.Execute(buffer, "")

return string(buffer.Bytes()) //=> "Alex"

But when I try to put the template in a file, it does not work (Execute() says: "alex" is an incomplete or empty template):

t, _ := template.New("alex").Funcs(funcMap).ParseFiles("template.html") 

With template.html:

{{label \"alex\"}}

Any idea why ? Is this a bug ? Are there simpler ways to use methods/functions in templates ?

答案1

得分: 34

ParseFiles可能需要更好的文档。一个模板对象可以包含多个模板,每个模板都有一个名称。如果你查看ParseFiles的实现,你会发现它使用filename作为模板对象内部的模板名称。所以,将文件命名为与模板对象相同的名称(可能通常不实际),或者使用ExecuteTemplate而不仅仅是Execute。

英文:

ParseFiles could probably use better documentation. A template object can have multiple templates in it and each one has a name. If you look at the implementation of ParseFiles, you see that it uses the filename as the template name inside of the template object. So, name your file the same as the template object, (probably not generally practical) or else use ExecuteTemplate instead of just Execute.

答案2

得分: 15

Sonia的答案在技术上是正确的,但让我更加困惑。以下是我最终让它工作的方法:

t, err := template.New("_base.html").Funcs(funcs).ParseFiles("../view/_base.html", "../view/home.html")
if err != nil {
	fmt.Fprint(w, "错误:", err)
	fmt.Println("错误:", err)
	return
}
err = t.Execute(w, data)
if err != nil {
	fmt.Fprint(w, "错误:", err)
	fmt.Println("错误:", err)
}

模板的名称是模板的纯文件名,而不是完整路径。如果默认模板的名称与之匹配,Execute将执行默认模板,因此不需要使用ExecuteTemplate

在这种情况下,_base.html文件是最外层的容器,例如:

<!DOCTYPE html>
<html><body>
<h1>{{ template "title" }}</h1>
{{ template "content" }}
</body></html>

home.html定义了具体的部分:

{{ define "title" }}Home{{ end }}

{{ define "content" }}
Stuff
{{ end }}
英文:

Sonia's answer is technically correct but left me even more confused. Here's how I eventually got it working:

t, err := template.New(&quot;_base.html&quot;).Funcs(funcs).ParseFiles(&quot;../view/_base.html&quot;, &quot;../view/home.html&quot;)
if err != nil {
	fmt.Fprint(w, &quot;Error:&quot;, err)
	fmt.Println(&quot;Error:&quot;, err)
	return
}
err = t.Execute(w, data)
if err != nil {
	fmt.Fprint(w, &quot;Error:&quot;, err)
	fmt.Println(&quot;Error:&quot;, err)
}

The name of the template is the bare filename of the template, not the complete path. Execute will execute the default template provided it's named to match, so there's no need to use ExecuteTemplate.

In this case, _base.html file is the outermost container, eg:

&lt;!DOCTYPE html&gt;
&lt;html&gt;&lt;body&gt;
&lt;h1&gt;{{ template &quot;title&quot; }}&lt;/h1&gt;
{{ template &quot;content&quot; }}
&lt;/body&gt;&lt;/html&gt;

while home.html defines the specific parts:

{{ define &quot;title&quot; }}Home{{ end }}

{{ define &quot;content&quot; }}
Stuff
{{ end }}

答案3

得分: 0

你需要首先解析所有的文件并执行它们。你不能直接访问所有的文件。

英文:

you need to first parse all the files and execute them .you cannot direclty access all the files .

huangapple
  • 本文由 发表于 2012年4月18日 05:11:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/10199219.html
匿名

发表评论

匿名网友

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

确定