2025年3月28日 星期五 甲辰(龙)年 月廿七 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Go语言

Golang 中的模板引擎

时间:12-14来源:作者:点击数:7
CDSY,CDSY.XYZ

常见 GO 语言的模板引擎

Iris offers support for 6 template parsers out of the box

Engine Declaration Underline Template Parser
std template/html iris.HTML(...) html/template package
django iris.Django(...) iris-contrib/pongo2 package
handlebars iris.Handlebars(...) Joker/jade package
amber iris.Amber(...) aymerick/raymond package
pug(jade) iris.Pug(...) eknkc/amber package
jet iris.Jet(...) CloudyKit/jet package

Go 模板

Go 模板是一种功能强大的定制输出的方法,无论您是在创建网页、发送电子邮件、使用 Buffalo、 Go-hugo 还是仅使用一些 CLI,比如 kubectl

Go 模板 控制结构

Control Structure Definition
{{/* a comment */}} Defines a comment
{{.}} Renders the root element
{{.Title}} Renders the “Title”-field in a nested element
{{if .Done}} {{else}} {{end}} Defines an if-Statement
{{range .Todos}} {{.}} {{end}} Loops over all “Todos” and renders each using {{.}}
{{block "content" .}} {{end}} Defines a block with the name “content”

Golang template 小抄

点字符 (.)

  1. 在 Go 语法中,模板变量可以是布尔值、字符串、字符、整数、浮点数、虚数或复数常量。 可以使用点{{ . }}访问传递到模板的数据 .
  2. 如果数据是复杂类型,则可以使用点{{ . FieldName }}访问其字段。
  3. 如果数据包含多个复杂结构,则可以将 Dots 链接在一起。{{ . Struct.StructTwo.Field }}

模板中的变量

  • {{$number := .}}
  • <h1> It is day number {{$number}} of the month </h1>

If/Else Statements

  • <h1>Hello, {{if .Name}} {{.Name}} {{else}} there {{end}}!</h1>

删除空白

我们可以通过忽略或最小化效果来更改我们的模板以更好地处理它,或者我们可以使用减号输出模板。

  • <h1>Hello, {{if .Name}} {{.Name}} {{- else}} Anonymous {{- end}}!</h1>

Range Blocks

  • type Item struct {
  • Name string
  • Price int
  • }
  • type ViewData struct {
  • Name string
  • Items []Item
  • }
  • {{range .Items}}
  • <div>
  • <h3>{{.Name}}</h3>
  • <span>${{.Price}}</span>
  • </div>
  • {{end}}

模板函数

获取索引值 {{index x number}}
  • <body>
  • <h1> {{index .FavNums 2 }}</h1>
  • </body>
  • type person struct {
  • Name string
  • FavNums []int
  • }
  • func main() {
  • tpl := template.Must(template.ParseGlob("*.gohtml"))
  • tpl.Execute(os.Stdout, &person{"Curtis", []int{7, 11, 94}})
  • }

and not 函数:

  • {{if and .User .User.Admin}}
  • You are an admin user!
  • {{else}}
  • Access denied!
  • {{end}}
  • type User struct {
  • Admin bool
  • }
  • type ViewData struct {
  • *User
  • }

比较函数 eq/ne/ge/gt/le/lt {{ op arg1 arg2 }}

eq 函数比较特殊,可以拿多个参数和第一个参数进行比较:

{{ eq arg1 arg2 arg3 arg4}} => arg1==arg2 || arg1==arg3 || arg1==arg4

管道

函数调用可以链式调用,前一个函数的输出结果作为下一个函数调用的参数。html/template称之为管道,类似于linux shell命令中的管道一样,它采用|分隔。

注意前一个命令的输出结果是作为下一个命令的最后一个参数,最终命令的输出结果就是这个管道的结果。

嵌套模板和布局

嵌套模板

嵌套模板可以用于经常跨模板、页脚或页眉使用的部分代码。 与分别更新每个模板不同,我们可以使用所有其他模板都可以使用的嵌套模板。

  • {{define "footer"}}
  • <footer>
  • <p>Here is the footer</p>
  • </footer>
  • {{end}}

定义了一个名为“ footer”的模板,可以在其他模板中使用,例如:

  • {{template "footer"}}
在模板之间传递变量

用于包含嵌套模板的template操作还允许第二个参数将数据传递给嵌套模板。

  • // Define a nested template called header
  • {{define "header"}}
  • <h1>{{.}}</h1>
  • {{end}}
  • // Call template and pass a name parameter
  • {{range .Items}}
  • <div>
  • {{template "header" .Name}}
  • <span>${{.Price}}</span>
  • </div>
  • {{end}}
创建布局
  • // Omitted imports & package
  • var LayoutDir string = "views/layouts"
  • var bootstrap *template.Template
  • func main() {
  • var err error
  • bootstrap, err = template.ParseGlob(LayoutDir + "/*.gohtml")
  • if err != nil {
  • panic(err)
  • }
  • http.HandleFunc("/", handler)
  • http.ListenAndServe(":8080", nil)
  • }
  • func handler(w http.ResponseWriter, r *http.Request) {
  • bootstrap.ExecuteTemplate(w, "bootstrap", nil)
  • }

views/layouts/bootstrap.gohtml 示例文件:

  • {{define "bootstrap"}}
  • <!DOCTYPE html>
  • <html lang="en">
  • <head>
  • <title>Go Templates</title>
  • <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  • </head>
  • <body>
  • <div>
  • <h1>Filler header</h1>
  • <p>Filler paragraph</p>
  • </div>
  • <!-- jquery & Bootstrap JS -->
  • <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  • <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  • </body>
  • </html>
  • {{end}}

模板中调用函数

  • type User struct {
  • ID int
  • Email string
  • }
  • func (u User) HasPermission(feature string) bool {
  • if feature == "feature-a" {
  • return true
  • } else {
  • return false
  • }
  • }
  • {{if .User.HasPermission "feature-a"}}
  • <div>
  • <h3>Feature A</h3>
  • <p>Some other stuff here...</p>
  • </div>
  • {{else}}
  • <div>
  • <h3>Feature A</h3>
  • <p>To enable Feature A please upgrade your plan</p>
  • </div>
  • {{end}}

如果方法 HasPermission 有时需要更改,则函数变量(方法)实现可能不适合设计。 相反,可以在 User 类型上添加 HasPermission func (string) bool 属性。 这样,在创建时就可以为它分配一个函数:

  • // Structs
  • type ViewData struct {
  • User User
  • }
  • type User struct {
  • ID int
  • Email string
  • HasPermission func(string) bool
  • }
  • // Example of creating a ViewData
  • vd := ViewData{
  • User: User{
  • ID: 1,
  • Email: "curtis.vermeeren@gmail.com",
  • // Create the HasPermission function
  • HasPermission: func(feature string) bool {
  • if feature == "feature-b" {
  • return true
  • }
  • return false
  • },
  • },
  • }
  • // Executing the ViewData with the template
  • err := testTemplate.Execute(w, vd)

call 关键字告诉 Go 模板我们想要调用这个函数:

  • {{if (call .User.HasPermission "feature-b")}}
  • <div>
  • <h3>Feature B</h3>
  • <p>Some other stuff here...</p>
  • </div>
  • {{else}}
  • <div>
  • <h3>Feature B</h3>
  • <p>To enable Feature B please upgrade your plan</p>
  • </div>
  • {{end}}

{{ "hello!" | upper | repeat 5 }}

生成

HELLO!HELLO!HELLO!HELLO!HELLO!

自定义函数

  • // Creating a template with function hasPermission
  • testTemplate, err = template.New("hello.gohtml").Funcs(template.FuncMap{
  • "hasPermission": func(user User, feature string) bool {
  • if user.ID == 1 && feature == "feature-a" {
  • return true
  • }
  • return false
  • },
  • }).ParseFiles("hello.gohtml")
  • {{ if hasPermission .User "feature-a" }}

自定义函数(全局)

大型应用程序中,向模板传递过多的对象可能会变得难以跨主模板进行维护。 我们可以将自定义函数的实现更改为不使用,例如创建一个默认的 hasPermission 函数:

  • testTemplate, err = template.New("hello.gohtml").Funcs(template.FuncMap{
  • "hasPermission": func(feature string) bool {
  • return false
  • },
  • }).ParseFiles("hello.gohtml")

这个函数可以放在 main ()或其他地方,以确保在 hello.gohtml 函数映射中创建默认的 hasPermission。 默认函数只返回 false,但它定义了不需要 User 的函数和实现。

接下来可以使用闭包重新定义 hasPermission 函数。 它将使用在处理程序中创建时可用的 User 数据,而不是将 User 数据传递给它。 在模板的处理程序中,您可以重新定义任何函数以使用可用的信息。

  • func handler(w http.ResponseWriter, r *http.Request) {
  • w.Header().Set("Content-Type", "text/html")
  • user := User{
  • ID: 1,
  • Email: "Curtis.vermeeren@gmail.com",
  • }
  • vd := ViewData{}
  • err := testTemplate.Funcs(template.FuncMap{
  • "hasPermission": func(feature string) bool {
  • return user.ID == 1 && feature == "feature-a"
  • },
  • }).Execute(w, vd)
  • if err != nil {
  • http.Error(w, err.Error(), http.StatusInternalServerError)
  • }
  • }

第三方自定义函数

除了官方的预定义的函数外,一些第三方也定义了一些函数,你可以使用这些库,避免重复造轮子。

比如 sprig 库,定义了很多的 函数

CDSY,CDSY.XYZ
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐