Go開源:hero-高性能、強大并且易用的 Go 模板引擎
Hero
Hero是一個高性能、強大并且易用的go模板引擎,工作原理是把模板預編譯為go代碼。Hero目前已經在 bthub.io 的線上環境上使用。
Features
- 非常易用.
- 功能強大,支持模板繼承和模板include.
- 高性能.
- 自動編譯.
Install
go get github.com/shiyanhui/hero
go install github.com/shiyanhui/hero/hero
Usage
hero [options]
options:
- source: 模板目錄,默認為當前目錄
- dest: 生成的go代碼的目錄,如果沒有設置的話,和source一樣
- pkgname: 生成的go代碼包的名稱,默認為template
- watch: 是否監控模板文件改動并自動編譯
example:
hero -source="./"
hero -source="$GOPATH/src/app/template" -watch</code></pre>
Quick Start
假設我們現在要渲染一個用戶列表模板 userlist.html , 它繼承自 index.html , 并且一個用戶的模板是 user.html . 我們還假設所有的模板都在 $GOPATH/src/app/template 目錄下。
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<%@ body { %>
<% } %>
</body>
</html></code></pre>
users.html
<%: func UserList(userList []string) []byte %>
<%~ "index.html" %>
<%@ body { %>
<% for _, user := range userList { %>
<ul>
<%+ "user.html" %>
</ul>
<% } %>
<% } %></code></pre>
user.html
<li>
<%= user %>
</li>
然后我們編譯這些模板:
hero -source="$GOPATH/src/app/template"
編譯后,我們將在同一個目錄下得到三個go文件,分別是 index.html.go , user.html.go and userlist.html.go , 然后我們在http server里邊去調用模板:
main.go
package main
import (
"app/template"
"net/http"
)
func main() {
http.HandleFunc("/users", func(w http.ResponseWriter, req *http.Request) {
var userList = []string {
"Alice",
"Bob",
"Tom",
}
w.Write(template.UserList(userList))
})
http.ListenAndServe(":8080", nil)
}</code></pre>
最后,運行這個http server,訪問 http://localhost:8080/users ,我們就能得到我們期待的結果了!
Template syntax
Hero總共有九種語句,他們分別是:
-
函數定義語句 <%: func define %>
- 該語句定義了該模板所對應的函數,如果一個模板中沒有函數定義語句,那么最終結果不會生成對應的函數。
- 該函數必須返回一個 []byte 參數。
- 例: <%: func UserList(userList []string) []byte %>
</li>
-
模板繼承語句 <%~ "parent template" %>
- 該語句聲明要繼承的模板。
- 例: <%~ "index.html" >
</ul> </li>
-
模板include語句 <%+ "sub template" %>
- 該語句把要include的模板加載進該模板,工作原理和 C++ 中的 #include 有點類似。
- 例: <%+ "user.html" >
</ul> </li>
-
包導入語句 <%! go code %>
-
該語句用來聲明所有在函數外的代碼,包括依賴包導入、全局變量、const等。
-
該語句不會被子模板所繼承
-
例:
<%!
import (
"fmt"
"strings"
)
var a int
const b = "hello, world"
func Add(a, b int) int {
return a + b
}
type S struct {
Name string
}
func (s S) String() string {
return s.Name
}
%></code></pre> </li>
</ul> </li>
-
塊語句 <%@ blockName { %> <% } %>
-
塊語句是用來在子模板中重寫父模中的同名塊,進而實現模板的繼承。
-
例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<%@ body { %>
<% } %>
</body>
</html></code></pre> </li>
</ul> </li>
-
Go代碼語句 <% go code %>
-
該語句定義了函數內部的代碼部分。
-
例:
<% for _, user := userList { %>
<% if user != "Alice" { %>
<%= user %>
<% } %>
<% } %>
<%
a, b := 1, 2
c := Add(a, b)
%></code></pre> </li>
</ul> </li>
-
原生值語句 <%== statement %>
-
該語句把變量轉換為string。
-
例:
<%== a %>
<%== a + b %>
<%== Add(a, b) %>
<%== user.Name %>
</ul> </li>
-
轉義值語句 <%= statement %>
-
該語句把變量轉換為string后,又通過 html.EscapesString 記性轉義。
-
例:
<%= a %>
<%= a + b %>
<%= Add(a, b) %>
<%= user.Name %>
</ul> </li>
-
注釋語句 <%# note %>
- 該語句注釋相關模板,注釋不會被生成到go代碼里邊去。
- 例: <# 這是一個注釋 > .
</ul> </li>
</ul>
License
Hero is licensed under the Apache License.