Go語言中的html/template標準庫學習筆記一(template庫的使用)

在MVC(model-view-controller)架構中,我們經常會用到模板文件,本片博文介紹html/template的使用方法,關於模板語法,請參考我的另一篇博客Go語言中的html/template標準庫學習筆記一(template語法介紹)

1.先介紹一下Template結構體

// Template is a specialized Template from "text/template" that produces a safe
// HTML document fragment.
type Template struct {
	// Sticky error if escaping fails, or escapeOK if succeeded.
	escapeErr error
	// We could embed the text/template field, but it's safer not to because
	// we need to keep our version of the name space and the underlying
	// template's in sync.
	text *template.Template
	// The underlying template's parse tree, updated to be HTML-safe.
	Tree       *parse.Tree
	*nameSpace // common to all associated templates
}

在Template中text爲*template.Template類型,保存了模板的基礎信息:

// Template is the representation of a parsed template. The *parse.Tree
// field is exported only for use by html/template and should be treated
// as unexported by all other clients.
type Template struct {
	name string
	*parse.Tree
	*common
	leftDelim  string
	rightDelim string
}

2.新建模板

我們可以使用func New(name string) *Template新建一個模板,並指定模板的名稱。

package main

import (
	"fmt"
	"html/template"
)

func main() {
    // 這裏我們創建了一個名稱爲test的模板
	tpl := template.New("test")
	// 查看模板名稱
	fmt.Println(tpl.Name())
}

Output:

$ go run main.go
test

3. 查看模板名稱

因爲name字段我們是不能直接查看的,因此我們需要使用func (t *Template) Name() string方法獲取模板名稱。

4.解析模板

(1)使用func ParseFiles(filenames ...string) (*Template, error)解析模板文件
我們在項目的templates目錄添加一個index.html文件,文件內容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>html/template教程</title>
</head>
<body>
    {{ . }}
</body>
</html>

文件中的{{ . }}表示接收到的內容,然後我們解析index.html模板:

package main

import (
	"html/template"
	"os"
)

func main() {
	tpl, err := template.ParseFiles("templates/index.html")
	if err != nil {
		panic(err)
	}
	// 如果不報錯則將內容輸出,os.Stdout爲標準輸出
	if err := tpl.Execute(os.Stdout, "hello world"); err != nil {
		panic(err)
	}
}

Output:

$ go run main.go
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>html/template教程</title>
</head>
<body>
    hello world
</body>
</html>

我們可以看到已經成功解析到了index.html模板,並且進行了渲染。

(2)使用func (t *Template) Parse(text string) (*Template, error)解析字符串

package main

import (
	"html/template"
	"os"
)

func main() {
    // 在Parse方法中傳入要解析的字符串`Output: {{ . }}`
	tpl, err := template.New("test").Parse(`Output: {{ . }}`)
	if err != nil {
		panic(err)
	}
	// 如果不報錯則將內容輸出,os.Stdout爲標準輸出
	if err := tpl.Execute(os.Stdout, "hello world"); err != nil {
		panic(err)
	}
}

Output:

$ go run main.go
Output: hello world

5.模板渲染

(1)使用func (t *Template) Execute(wr io.Writer, data interface{}) error渲染模板,這個在前面已經用到了,就不舉例了。
(2)使用func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error渲染指定模板
package main

import (
	"html/template"
	"os"
)

func main() {
    // 在Parse方法中傳入要解析的字符串`Output: {{ . }}`
	tpl, err := template.New("test").Parse(`Output: {{ . }}`)
	if err != nil {
		panic(err)
	}
	// 如果不報錯則將內容輸出,os.Stdout爲標準輸出
	if err := tpl.ExecuteTemplate(os.Stdout, "test", "hello world"); err != nil {
		panic(err)
	}
}

Output:

$ go run main.go
Output: hello world
(3)`func ParseGlob(pattern string) (*Template, error)

`ParseGlob函數從指定的匹配文件中創建並解析模板,必須得至少匹配一個文件.
這裏我們在templates目錄創建兩個文件:
body.html文件內容爲:

{{ define "body" }}
<body>
    <p>Hello World</p>
</body>
{{ end }}

header.html文件內容爲:

<!DOCTYPE html>
<html>
<head> 
    <meta charset="utf-8"> 
    <title>html/template教程</title> 
</head>
    {{ template "body" . }}
</html>

我們使用ParseGlob進行模板解析:

package main

import (
	"html/template"
	"os"
)
func main() {
	tpl, err := template.ParseGlob("templates/*.html")
	if err != nil {
		panic(err)
	}
	// 如果不報錯則將內容輸出,os.Stdout爲標準輸出
	if err := tpl.ExecuteTemplate(os.Stdout, "header.html", nil); err != nil {
		panic(err)
	}
}

Output:

$ go run main.go
<!DOCTYPE html>
<html>
<head> 
    <meta charset="utf-8"> 
    <title>html/template教程</title> 
</head>

<body>
    <p>Hello World</p>
</body>

</html>

6.添加模板函數

模板文件中支持函數操作,我們可以使用func (t *Template) Funcs(funcMap FuncMap) *Template方法給模板添加函數,模板函數的返回值最多爲兩個,並且如果有第二個參數,則必須爲error類型。

package main

import (
	"html/template"
	"os"
	"strings"
)
// 定義模板函數返回hello world
func Hello() (string, error) {
	return "hello world", nil
}
func main() {
	// 首先創建一個函數字典用於註冊函數
	funcMap := template.FuncMap{
		"hello": Hello,
	}
	tpl, err := template.New("test").Funcs(funcMap).Parse(`Output: {{ hello }}`)
	if err != nil {
		panic(err)
	}
	// 如果不報錯則將內容輸出,os.Stdout爲標準輸出
	if err := tpl.Execute(os.Stdout, "hello world"); err != nil {
		panic(err)
	}
}

Output:

$ go run main.go
Output: hello world

7. 其他方法

(1)func Must(t *Template, err error) *Template

Must函數會在Parse返回err不爲nil時,調用panic,不需要初始化後再調用Parse方法去檢測,下面舉個例子:

package main

import (
	"html/template"
	"os"
)

func main() {
	//	Must會判斷解析結果是否報錯,如果報錯則panic
	// {{ templates/*.html是錯誤的模板語法,因此會報錯
	tpl := template.Must(template.New("test").Parse("{{ templates/*.html"))

	// 如果不報錯則將內容輸出,os.Stdout爲標準輸出
	if err := tpl.ExecuteTemplate(os.Stdout, "test", nil); err != nil {
		panic(err)
	}
}

Output:

$ go run main.go
panic: template: test:1: unexpected bad character U+002F '/' in command

goroutine 1 [running]:
html/template.Must(...)
        c:/Go/src/html/template/template.go:372
main.main()
        D:/GOCODE/Test/main.go:15 +0xff
exit status 2
(2)func (t *Template) Delims(left, right string) *Template

Delims可以自定義模板中的分界符號,默認是{{}}

package main

import (
	"html/template"
	"os"
)

func main() {
	//	## Delims()方法用來指定分隔符來分割字符串,隨後會使用Parse, ParseFiles, or ParseGlob方法進行模板內容解析
	tpl := template.Must(template.New("test").Delims("{{", "]]").Parse("{{ . ]]"))
	// 如果不報錯則將內容輸出,os.Stdout爲標準輸出
	if err := tpl.Execute(os.Stdout, "hello world"); err != nil {
		panic(err)
	}
}

Output:

$ go run main.go
hello world

可以看到界定符被改成{{]],程序正確對模塊進行了解析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章