Goh is a blazing-fast, pre-compiled template engine for the Go language.
简体中文 | English
Table of Contents
Features
- Pre-compiled template engine to boost runtime performance.
- Near-complete Go syntax compatibility.
- Zero dependencies.
Automatic re-compilation on template file changes.
Performance Benchmarks
Results obtained from github.com/slinso/goTemplateBenchmark. These are local test results using the same code as the Hero benchmark. BenchmarkComplexGoDirectBuffer
and BenchmarkComplexGoStaticString
write directly to a buffer and a static string, respectively, so they are not included in the ranking. Goh ranks first among complex template tests.
goos: windows
goarch: amd64
pkg: github.com/SlinSo/goTemplateBenchmark
cpu: Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
# Complex Template Benchmark
BenchmarkComplexGolang-16 36800 31428 ns/op 6562 B/op 290 allocs/op
BenchmarkComplexGolangText-16 88148 13370 ns/op 2235 B/op 107 allocs/op
BenchmarkComplexEgo-16 486294 2411 ns/op 568 B/op 31 allocs/op
BenchmarkComplexQuicktemplate-16 1367928 878.1 ns/op 0 B/op 0 allocs/op
BenchmarkComplexTempl-16 788673 1400 ns/op 408 B/op 11 allocs/op
BenchmarkComplexFtmpl-16 293755 3982 ns/op 3534 B/op 38 allocs/op
BenchmarkComplexFtmplInclude-16 317361 4142 ns/op 3534 B/op 38 allocs/op
BenchmarkComplexMustache-16 90567 13748 ns/op 7274 B/op 156 allocs/op
BenchmarkComplexGorazor-16 361304 3195 ns/op 3688 B/op 24 allocs/op
BenchmarkComplexJetHTML-16 189176 5928 ns/op 532 B/op 5 allocs/op
BenchmarkComplexHero-16 1410391 863.5 ns/op 0 B/op 0 allocs/op
BenchmarkComplexGoh-16 2304783 535.4 ns/op 0 B/op 0 allocs/op
BenchmarkComplexJade-16 1826784 651.8 ns/op 0 B/op 0 allocs/op
BenchmarkComplexGoDirectBuffer-16 2890996 414.6 ns/op 0 B/op 0 allocs/op
BenchmarkComplexGoHyperscript-16 1717754 778.6 ns/op 0 B/op 0 allocs/op
BenchmarkComplexGoStaticString-16 84003024 14.44 ns/op 0 B/op 0 allocs/op
# Simple Template Benchmark
BenchmarkGolang-16 300493 3691 ns/op 768 B/op 35 allocs/op
BenchmarkGolangText-16 1000000 1073 ns/op 128 B/op 7 allocs/op
BenchmarkGoDirectBuffer-16 21959280 55.81 ns/op 0 B/op 0 allocs/op
BenchmarkGoCustomHtmlAPI-16 14034298 85.06 ns/op 0 B/op 0 allocs/op
BenchmarkGoFunc3-16 14962965 68.62 ns/op 0 B/op 0 allocs/op
BenchmarkEgo-16 2577276 464.3 ns/op 85 B/op 8 allocs/op
BenchmarkHB-16 280617 4445 ns/op 2448 B/op 51 allocs/op
BenchmarkQuicktemplate-16 7013572 168.9 ns/op 0 B/op 0 allocs/op
BenchmarkFtmpl-16 1000000 1000 ns/op 774 B/op 12 allocs/op
BenchmarkAce-16 179811 6605 ns/op 1121 B/op 40 allocs/op
BenchmarkAmber-16 268149 3800 ns/op 849 B/op 36 allocs/op
BenchmarkMustache-16 523143 2636 ns/op 1722 B/op 30 allocs/op
BenchmarkPongo2-16 350612 3862 ns/op 2074 B/op 32 allocs/op
BenchmarkHandlebars-16 162860 7261 ns/op 3423 B/op 75 allocs/op
BenchmarkGorazor-16 1562088 772.3 ns/op 512 B/op 5 allocs/op
BenchmarkSoy-16 639549 2200 ns/op 1224 B/op 19 allocs/op
BenchmarkJetHTML-16 1960117 600.4 ns/op 0 B/op 0 allocs/op
BenchmarkHero-16 10452396 113.9 ns/op 0 B/op 0 allocs/op
BenchmarkGoh-16 14838537 81.97 ns/op 0 B/op 0 allocs/op
BenchmarkJade-16 15025261 78.85 ns/op 0 B/op 0 allocs/op
BenchmarkTempl-16 4015622 293.1 ns/op 96 B/op 2 allocs/op
BenchmarkGomponents-16 479330 2882 ns/op 1112 B/op 56 allocs/op
ok github.com/SlinSo/goTemplateBenchmark 65.553s
Installation
go get -u github.com/OblivionOcean/Goh
go install github.com/OblivionOcean/Goh
# Dependencies
go get golang.org/x/tools/cmd/goimports
go install golang.org/x/tools/cmd/goimports
Usage
~ $ Goh
Usage of ./Goh:
-dest string
generated golang files dir, it will be the same with source if not set
-ext string
source file extensions, comma splitted if many (default ".html")
-pkg string
the generated template package name, default is template (default "template")
-src string
the html template file or directory (default "./")
For a complete guide, please refer to the example project.
<%: func UserList(title string, userList []string, buf *bytes.Buffer) %>
<!DOCTYPE html>
<html>
<head>
<title>
<%= title %>
</title>
</head>
<body>
<h1>
<%= title %>
</h1>
<ul>
<% for _, user :=range userList { %>
<% if user !="Alice" { %>
<li>
<%= user %>
</li>
<% } %>
<% } %>
</ul>
</body>
</html>
package main
import (
"bytes"
"net/http"
"github.com/OblivionOcean/Goh/example/template"
)
func main() {
http.HandleFunc("/users", func(w http.ResponseWriter, req *http.Request) {
var userList = []string{
"Alice",
"Bob",
"Tom",
}
buffer := new(bytes.Buffer)
template.UserList("User List", userList, buffer)
w.Write(buffer.Bytes())
})
http.ListenAndServe(":8080", nil)
}
Syntax
Documentation adapted from shiyanhui/hero.
Goh supports nine types of statements:
-
Function Definition
<%: func define %>
- Defines the corresponding function for a template. If a template has no function definition statement, no function will be generated for it.
- The last parameter of the function must be
*bytes.Buffer
orio.Writer
. Goh automatically recognizes the name of this parameter and writes the output to it. - Example:
<%: func UserList(userList []string, buffer *bytes.Buffer) %>
<%: func UserList(userList []string, w io.Writer) %>
<%: func UserList(userList []string, w io.Writer) (int, error) %>
-
Template Inheritance
<%~ "parent template" %>
- Declares the parent template to be inherited.
- Example:
<%~ "index.html" >
-
Template Include
<%+ "sub template" %>
- Includes a sub-template into the current one, similar to
#include
in C++. - Example:
<%+ "user.html" >
- Includes a sub-template into the current one, similar to
-
Package Import
<%! go code %>
- This statement is used to declare all code outside the function body, including package imports, global variables, constants, etc.
- This statement is not inherited by child templates.
-
Example:
<%! 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 } %>
-
Block
<%@ blockName { %> <%@ } %>
[!WARNING]
Unlike Hero, the closing block statement must be<%@ } %>
instead of<% } %>
.
This change was made to improve compiler performance and reduce compilation time.- Block statements are used to override a parent template's block with the same name, enabling template inheritance.
-
Example:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <%@ body { %> <%@ } %> </body> </html>
-
Go Code
<% go code %>
- Defines the Go code section within the function body.
-
Example:
<% for _, user := range userList { %> <% if user != "Alice" { %> <%= user %> <% } %> <% } %> <% a, b := 1, 2 c := Add(a, b) %>
-
Raw Value
<%==[t] variable %>
or<%- variable %>
- Converts a variable to a string.
-
t
is the variable's type, and Goh will automatically select the conversion function based on it. The available values fort
are:-
b
: bool -
i
: int, int8, int16, int32, int64 -
u
: byte, uint, uint8, uint16, uint32, uint64 -
f
: float32, float64 -
s
: string -
bs
: []byte -
v
: interface
-
-
Note:
- If
t
is not specified, it defaults tos
. - It's best to avoid using
v
as its corresponding conversion function,fmt.Sprintf("%v", variable)
, is very slow.
- If
-
Example:
<%== "hello" %> <%==i 34 %> <%==u Add(a, b) %> <%==s user.Name %>
-
Escaped Value
<%= statement %>
- Converts a variable to a string and then escapes it using
html.EscapesString
. -
t
is the same as in the Raw Value statement above. -
Example:
<%= a %> <%= a + b %> <%= Add(a, b) %> <%= user.Name %>
- Converts a variable to a string and then escapes it using
-
Comment
<%# note %>
- This statement is a comment and will not be generated into the Go code.
- Example:
<# This is a comment >
.
Top comments (0)