Hero is a handy, fast and powerful go template engine, which pre-compiles the html templates to go code. It has been used in production environment in bthub.io.
- High performance.
- Easy to use.
- Powerful. template
ExtendandIncludesupported. - Auto compiling when files change.
Hero is the fastest and least-memory used among currently known template engines in the benchmark. The data of chart comes from https://github.com/SlinSo/goTemplateBenchmark. You can find more details and benchmarks from that project.
go get github.com/shiyanhui/hero/hero # Hero needs `goimports` to format the generated codes. go get golang.org/x/tools/cmd/goimportshero [options] -source string the html template file or dir (default "./") -dest string generated golang files dir, it will be the same with sourceif not set -extensions string source file extensions, comma splitted if many (default ".html") -pkgname template the generated template package name, default is template (default "template") -watch whether automatically compile when the source files change example: hero -source="./" hero -source="$GOPATH/src/app/template" -dest="./" -extensions=".html,.htm" -pkgname="t" -watchAssume that we are going to render a user list userlist.html. index.html is the layout, and user.html is an item in the list.
And assumes that they are all under $GOPATH/src/app/template
<!DOCTYPE html><html><head><metacharset="utf-8"></head><body><%@ body{%><% } %></body></html><%: func UserList(userList []string, buffer *bytes.Buffer) %><%~ "index.html" %><%@ body{%><% for _, user := range userList{%><ul><%+ "user.html" %></ul><% } %><% } %><li><%= user %></li>Then we compile the templates to go code.
hero -source="$GOPATH/src/app/template"We will get three new .go files under $GOPATH/src/app/template, i.e. index.html.go, user.html.go and userlist.html.go.
Then we write a http server in $GOPATH/src/app/main.go.
package main import ( "bytes""net/http""app/template" ) funcmain(){http.HandleFunc("/users", func(w http.ResponseWriter, req*http.Request){varuserList= []string{"Alice", "Bob", "Tom", } // Had better use buffer pool. Hero exports `GetBuffer` and `PutBuffer` for this.//// For convenience, hero also supports `io.Writer`. For example, you can also define// the function to `func UserList(userList []string, w io.Writer) (int, error)`,// and then://// template.UserList(userList, w)//buffer:=new(bytes.Buffer) template.UserList(userList, buffer) w.Write(buffer.Bytes()) }) http.ListenAndServe(":8080", nil) }At last, start the server and visit http://localhost:8080/users in your browser, we will get what we want!
There are only nine necessary kinds of statements, which are:
Function Definition
<%: func define %>- Function definition statement defines the function which represents an html file.
- The type of the last parameter in the function defined should be
*bytes.Bufferfor manual buffer management orio.Writerfor automatic buffer management ( note: if usingio.Writeryou may optionally specify return values(int, error)to handle the result ofio.Writer.Write). Hero will identify the parameter name automaticly. - Example:
<%: func UserList(userList []string, buffer *bytes.Buffer) %><%: func UserList(userList []string, w io.Writer) %><%: func UserList(userList []string, w io.Writer) (int, error) %>
Extend
<%~ "parent template" %>- Extend statement states the parent template the current template extends.
- The parent template should be quoted with
"". - Example:
<%~ "index.html" >, which we have mentioned in quick start, too.
Include
<%+ "sub template" %>- Include statement includes a sub-template to the current template. It works like
#includeinC++. - The sub-template should be quoted with
"". - Example:
<%+ "user.html" >, which we also have mentioned in quick start.
- Include statement includes a sub-template to the current template. It works like
Import
<%! go code %>Import statement imports the packages used in the defined function, and it also contains everything that is outside of the defined function.
Import statement will NOT be inherited by child template.
Example:
<%!import ( "fmt""strings" ) varaintconstb="hello, world"funcAdd(a, bint) int{returna+b } typeSstruct{Namestring } func (sS) String() string{returns.Name } %>
Block
<%@ blockName{%> <% } %>Block statement represents a block. Child template overwrites blocks to extend parent template.
Example:
<!DOCTYPE html><html><head><metacharset="utf-8"></head><body><%@ body{%><% } %></body></html>
Code
<% go code %>Code statement states all code inside the defined function. It's just go code.
Example:
<%for_, user:=rangeuserList{%><%ifuser!="Alice"{%><%=user%><% } %><% } %><%a, b:=1, 2c:=Add(a, b) %>
Raw Value
<%==[t] variable %>Raw Value statement will convert the variable to string.
tis the type of variable, hero will find suitable converting method byt. Candidates oftare:b: booli: int, int8, int16, int32, int64u: byte, uint, uint8, uint16, uint32, uint64f: float32, float64s: stringbs: []bytev: interface
Note:
- If
tis not set, the value oftiss. - Had better not use
v, cause whent=v, the converting method isfmt.Sprintf("%v", variable)and it is very slow.
Example:
<%=="hello"%><%==i34%><%==uAdd(a, b) %><%==suser.Name%>
Escaped Value
<%=[t] variable %>Escaped Value statement is similar with Raw Value statement, but after converting, it will be escaped it with
html.EscapesString.tis the same as inRaw Value Statement.Example:
<%=a%><%=ia+b%><%=uAdd(a, b) %><%=bs []byte{1, 2} %>
Note
<%# note %>- Note statement add notes to the template.
- It will not be added to the generated go source.
- Example:
<# this is just a note example>.
Hero is licensed under the Apache License.

