How do you add the current year to a Go template?

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

How do you add the current year to a Go template?

问题

在Go模板中,你可以像这样检索一个字段:

template.Parse("<html><body>{{ .Title }}</body></html>")
template.Execute(w, myObject)

你想要如何“内联”当前的UTC年份?我想要做类似这样的操作:

template.Parse("<html><body>The current year is {{time.Now.UTC.Year}}</body></html>")

但是它返回错误信息:

panic: template: function "time" not defined

英文:

In a Go template, you can retrieve a field like this:

template.Parse(&quot;&lt;html&gt;&lt;body&gt;{{ .Title }}&lt;/body&gt;&lt;/html&gt;&quot;)
template.Execute(w, myObject)

How would you "inline" the current UTC year? I want to do something like this:

template.Parse(&quot;&lt;html&gt;&lt;body&gt;The current year is {{time.Time.Now().UTC().Year()}}&lt;/body&gt;&lt;/html&gt;&quot;)

But it returns the error:

> panic: template: function "time" not defined

答案1

得分: 13

你可以向模板中添加函数,尝试以下代码:

package main

import (
	"html/template"
	"log"
	"os"
	"time"
)

func main() {
	funcMap := template.FuncMap{
		"now": time.Now,
	}

	templateText := `<html><body>The current year is {{now.UTC.Year}}</body></html>`
	tmpl, err := template.New("titleTest").Funcs(funcMap).Parse(templateText)
	if err != nil {
		log.Fatalf("parsing: %s", err)
	}

	// 运行模板以验证输出。
	err = tmpl.Execute(os.Stdout, nil)
	if err != nil {
		log.Fatalf("execution: %s", err)
	}
}

这段代码向模板中添加了一个名为now的函数,该函数返回当前时间。模板文本中使用了{{now.UTC.Year}}来获取当前年份,并将其插入到HTML中。最后,通过执行模板将结果输出到标准输出。

英文:

you can add function to template, try this:

package main

import (
	&quot;html/template&quot;
	&quot;log&quot;
	&quot;os&quot;
	&quot;time&quot;
)

func main() {
	funcMap := template.FuncMap{
		&quot;now&quot;: time.Now,
	}

	templateText := &quot;&lt;html&gt;&lt;body&gt;The current year is {{now.UTC.Year}}&lt;/body&gt;&lt;/html&gt;&quot;
	tmpl, err := template.New(&quot;titleTest&quot;).Funcs(funcMap).Parse(templateText)
	if err != nil {
		log.Fatalf(&quot;parsing: %s&quot;, err)
	}

	// Run the template to verify the output.
	err = tmpl.Execute(os.Stdout, nil)
	if err != nil {
		log.Fatalf(&quot;execution: %s&quot;, err)
	}
}

答案2

得分: 2

你已经在模板中包含了一个Title。它是如何出现在模板中的呢?你可以将它作为参数传递给Template.Execute()。这个方法同样适用于当前年份。

这是一个比注册函数更好、更简单的解决方案。代码如下所示:

t := template.Must(template.New("").Parse(
    "<html><body>{{ .Title }}; Year: {{.Year}}</body></html>"))

myObject := struct {
    Title string
    Year  int
}{"Test Title", time.Now().UTC().Year()}

if err := t.Execute(os.Stdout, myObject); err != nil {
    fmt.Println(err)
}

输出结果(在Go Playground上尝试):

<html><body>Test Title; Year: 2009</body></html>

(注意:Go Playground 上的当前日期/时间是 2009-11-10 23:00:00,所以你看到的是 2009)。

根据设计原则,模板不应包含复杂的逻辑。如果模板中有某些内容过于复杂,你应该考虑在 Go 代码中计算结果,然后将结果作为数据传递给模板执行,或者在模板中注册一个回调函数,并在模板操作中调用该函数并插入返回值。

可以说获取当前年份并不是一个复杂的逻辑。但是,Go 是一种静态链接语言。你只能确保可执行二进制文件仅包含你的 Go(源代码)显式引用的包和函数。这适用于标准库的所有包(除了runtime包)。因此,模板文本不能直接引用和调用像time包这样的包中的函数,因为不能保证在运行时会有这些函数可用。

英文:

You're already including a Title in your template. How does that end up in the template? You pass it as an argument to Template.Execute(). This (unsurprisingly) works for the current year too.

It's a better and easier solution than registering a function for this. This is how it could look like:

t := template.Must(template.New(&quot;&quot;).Parse(
	&quot;&lt;html&gt;&lt;body&gt;{{ .Title }}; Year: {{.Year}}&lt;/body&gt;&lt;/html&gt;&quot;))

myObject := struct {
	Title string
	Year  int
}{&quot;Test Title&quot;, time.Now().UTC().Year()}

if err := t.Execute(os.Stdout, myObject); err != nil {
	fmt.Println(err)
}

Output (try it on the Go Playground):

&lt;html&gt;&lt;body&gt;Test Title; Year: 2009&lt;/body&gt;&lt;/html&gt;

(Note: the current date/time on the Go Playground is 2009-11-10 23:00:00, that's why you see 2009).

By design philosophy, templates should not contain complex logic. If something is (or looks) too complex in templates, you should consider calculating the result in Go code and either pass the result as data to the execution, or register a callback function in the templates and have a template action call that function and insert the return value.

Arguably getting the current year is not a complex logic. But Go is a statically linked language. You only have guarantee that the executable binary will only include packages and functions that your Go (source) code refers to explicitly. This applies to all packages of the standard library (except the runtime package). So a template text cannot just refer to and call functions from packages like the time package, because there is no guarantee that will be available at runtime.

huangapple
  • 本文由 发表于 2017年3月20日 12:29:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/42895877.html
匿名

发表评论

匿名网友

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

确定