gorazor is the Go port of the Razor view engine originated from ASP.NET in 2011. In summary, gorazor is:
<?, <%, or {{.
gorazor is about 20X faster than html/template when using standard strings.Builder for template writing.
When using quicktemplate's ByteBuffer and unsafeStrToBytes method to for template writing, gorazor's performance is comparable to quicktemplate, if not faster.
Benchmark results:
$ cd tests && go test -bench='Benchmark(Razor|RazorQuick|Quick|HTML)Template' -benchmem
goos: windows
goarch: amd64
pkg: github.com/valyala/quicktemplate/tests
BenchmarkQuickTemplate1-8 50000000 35.6 ns/op 0 B/op 0 allocs/op
BenchmarkQuickTemplate10-8 10000000 152 ns/op 0 B/op 0 allocs/op
BenchmarkQuickTemplate100-8 1000000 1460 ns/op 0 B/op 0 allocs/op
BenchmarkHTMLTemplate1-8 2000000 712 ns/op 608 B/op 21 allocs/op
BenchmarkHTMLTemplate10-8 500000 3586 ns/op 2834 B/op 111 allocs/op
BenchmarkHTMLTemplate100-8 50000 35180 ns/op 28055 B/op 1146 allocs/op
PASS
ok github.com/valyala/quicktemplate/tests 11.360s
goos: windows
goarch: amd64
pkg: github.com/sipin/gorazor/tests
BenchmarkRazorTemplate1-8 30000000 49.8 ns/op 224 B/op 3 allocs/op
BenchmarkRazorTemplate10-8 10000000 122 ns/op 480 B/op 4 allocs/op
BenchmarkRazorTemplate100-8 2000000 931 ns/op 4064 B/op 7 allocs/op
BenchmarkRazorQuickTemplate1-8 100000000 19.9 ns/op 0 B/op 0 allocs/op
BenchmarkRazorQuickTemplate10-8 20000000 82.5 ns/op 0 B/op 0 allocs/op
BenchmarkRazorQuickTemplate100-8 2000000 767 ns/op 0 B/op 0 allocs/op
BenchmarkRazorQuickTemplateOriginal1-8 100000000 17.4 ns/op 0 B/op 0 allocs/op
BenchmarkRazorQuickTemplateOriginal10-8 20000000 68.8 ns/op 0 B/op 0 allocs/op
BenchmarkRazorQuickTemplateOriginal100-8 2000000 656 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/sipin/gorazor/tests 19.921s
BenchmarkRazorQuickTemplate is manually modified to ensure exact output as quicktemplate for comparison.BenchmarkRazorQuickTemplateOriginal are gorazor's default code-gen, which produce less white-space, thus faster.gorazor supports go 1.10 and above, for go version below 1.10, you may use gorazor classic version.
go 1.12 and above are recommended for better compiler optimization.
go install github.com/sipin/gorazor@latest
Check out our step-by-step Quick Start Guide to build and run your first compiled template in under 5 minutes.
gorazor template_folder output_foldergorazor template_file output_fileThe Examples directory gives examples using layouts, helpers, etc.
When using layouts, you may need to set the -prefix parameter:
git clone https://github.com/sipin/gorazor/
cd gorazor
go build
# The -prefix parameter here tells gorazor the current folder is the base path for github.com/sipin/gorazor.
# So that, when importing "github.com/sipin/gorazor/examples/tpl/layout" in examples/tpl/home.gohtml,
# gorazor will know how to find the layout/helper files.
./gorazor -prefix github.com/sipin/gorazor ./examples/tpl ./examples/tpl
go run examples/main.go
@variable to insert string variable into html template
<div>Hello @user.Name</div>
<div>Hello @strings.ToUpper(req.CurrentUser.Name)</div>
Use raw to skip escaping:
<div>@raw(user.Name)</div>
Only use raw when you are 100% sure what you are doing. Please always be aware of XSS attacks.
@if .... {
....
}
@if .... {
....
} else {
....
}
@for .... {
}
@{
switch .... {
case ....:
<p>...</p>
case 2:
<p>...</p>
default:
<p>...</p>
}
}
Please use example for reference.
Arbitrary go code could be used in templates, like creating a new variable.
@{
username := u.Name
if u.Email != "" {
username += "(" + u.Email + ")"
}
}
<div class="welcome">
<h4>Hello @username</h4>
</div>
It's recommended to keep clean separation of code & view. Please consider move logic into your code before creating a code block in a template.
The first code block in template is strictly for declaration:
like:
@{
import (
"kp/models" //import `"kp/models"` package
"tpl/layout" //import tpl/layout namespace
)
layout := layout.Base //Use layout package's **Base func** for layout
var user *models.User //1st template param
var blog *models.Blog //2nd template param
}
...
first code block must be at the beginning of the template, i.e. before any html.
Any other codes inside the first code block will be ignored.
import must be wrapped in (), import "package_name" is not yet supported.
The variables declared in first code block will be the models of the template, i.e. the parameters of generated function.
If your template doesn't need any model input, then just leave it blank.
As gorazor compiles templates to go function, embedding another template is just calling the generated function, like any other go function.
However, if the templates are designed to be embedded, they must be under helper namespace, i.e. put them in helper sub-folder.
So, using a helper template is similar to:
@if msg != "" {
<div>@helper.ShowMsg(msg)</div>
}
gorazor won't HTML escape the output of helper.XXX.
Please use example for reference.
The syntax for declaring layout is a bit tricky, in the example mentioned above:
@{
import (
"tpl/layout"
)
layout := layout.Base //Use layout package's **base func** for layout
}
"tpl/layout" is the layout package namespace, and the layout variable refers to "layout.Base" func, which should be generated by tpl/layout/base.gohtml.
Must use
layoutas the variable name
layout
gorazor relies on this to determine if a template is for layoutvariable name also must be layoutA layout file tpl/layout/base.gohtml may look like:
@{
var body string
var sidebar string
var footer string
var title string
var css string
var js string
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@title</title>
</head>
<body>
<div class="container">@body</div>
<div class="sidebar">@sidebar</div>
<div class="footer">@footer</div>
@js
</body>
</html>
It's just a usual gorazor template, but:
var body string (As it's always required, maybe we could remove it in future?)layout package, i.e. within "layout" folder.
isLayout := true to declare a template as layoutA template using such layout tpl/index.gohtml may look like:
@{
import (
"tpl/layout"
)
layout := layout.Base
}
@section footer {
<div>Copyright 2014</div>
}
<h2>Welcome to homepage</h2>
It's also possible to use import alias:
@{
import (
share "tpl/layout"
)
layout := share.Base
}
With the page, the page content will be treated as the body section in the layout.
The other section content need to be wrapped with
@section SectionName {
....
}
The template doesn't need to specify all sections defined in the layout. If a section is not specified, it will be considered as "".
Thus, it's possible for the layout to define default section content in such manner:
@{
var body string
var sidebar string
}
<body>
<div class="container">@body</div>
@if sidebar == "" {
<div class="sidebar">I'm the default side bar</div>
} else {
<div class="sidebar">@sidebar</div>
}
</body>
.gohtml..gohtml extension) will be used as the function name in the generated code, with the first letter capitalized (making it exported in Go).helper folder).layout folder).Here is a simple example of gorazor templates and generated Go code.
gorazor via Package Control.gscomplete.py in with this and gslint.py with thisweb-mode supports Razor template engine, so add this into your Emacs config file:
(require 'web-mode)
(add-hook 'web-mode-hook 'my-web-mode-hook)
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.gohtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.js\\'" . web-mode))
(setq web-mode-engines-alist '(("razor" . "\\.gohtml\\'")))
The very first version of gorazor is a hack of razor's port in javascript: vash, thus requires node's to run.
gorazor has been though several rounds of refactoring, and it has completely rewritten in pure Go. Nonetheless, THANK YOU @kirbysayshi for Vash! Without Vash, gorazor may never start.
LICENSE? Well, WTFPL and 996.icu.
Feature completed.
Archived todo
Go
80.1%
Go Template
19.4%
gorazor is the Go port of the Razor view engine originated from ASP.NET in 2011. In summary, gorazor is:
<?, <%, or {{.
gorazor is about 20X faster than html/template when using standard strings.Builder for template writing.
When using quicktemplate's ByteBuffer and unsafeStrToBytes method to for template writing, gorazor's performance is comparable to quicktemplate, if not faster.
Benchmark results:
$ cd tests && go test -bench='Benchmark(Razor|RazorQuick|Quick|HTML)Template' -benchmem
goos: windows
goarch: amd64
pkg: github.com/valyala/quicktemplate/tests
BenchmarkQuickTemplate1-8 50000000 35.6 ns/op 0 B/op 0 allocs/op
BenchmarkQuickTemplate10-8 10000000 152 ns/op 0 B/op 0 allocs/op
BenchmarkQuickTemplate100-8 1000000 1460 ns/op 0 B/op 0 allocs/op
BenchmarkHTMLTemplate1-8 2000000 712 ns/op 608 B/op 21 allocs/op
BenchmarkHTMLTemplate10-8 500000 3586 ns/op 2834 B/op 111 allocs/op
BenchmarkHTMLTemplate100-8 50000 35180 ns/op 28055 B/op 1146 allocs/op
PASS
ok github.com/valyala/quicktemplate/tests 11.360s
goos: windows
goarch: amd64
pkg: github.com/sipin/gorazor/tests
BenchmarkRazorTemplate1-8 30000000 49.8 ns/op 224 B/op 3 allocs/op
BenchmarkRazorTemplate10-8 10000000 122 ns/op 480 B/op 4 allocs/op
BenchmarkRazorTemplate100-8 2000000 931 ns/op 4064 B/op 7 allocs/op
BenchmarkRazorQuickTemplate1-8 100000000 19.9 ns/op 0 B/op 0 allocs/op
BenchmarkRazorQuickTemplate10-8 20000000 82.5 ns/op 0 B/op 0 allocs/op
BenchmarkRazorQuickTemplate100-8 2000000 767 ns/op 0 B/op 0 allocs/op
BenchmarkRazorQuickTemplateOriginal1-8 100000000 17.4 ns/op 0 B/op 0 allocs/op
BenchmarkRazorQuickTemplateOriginal10-8 20000000 68.8 ns/op 0 B/op 0 allocs/op
BenchmarkRazorQuickTemplateOriginal100-8 2000000 656 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/sipin/gorazor/tests 19.921s
BenchmarkRazorQuickTemplate is manually modified to ensure exact output as quicktemplate for comparison.BenchmarkRazorQuickTemplateOriginal are gorazor's default code-gen, which produce less white-space, thus faster.gorazor supports go 1.10 and above, for go version below 1.10, you may use gorazor classic version.
go 1.12 and above are recommended for better compiler optimization.
go install github.com/sipin/gorazor@latest
Check out our step-by-step Quick Start Guide to build and run your first compiled template in under 5 minutes.
gorazor template_folder output_foldergorazor template_file output_fileThe Examples directory gives examples using layouts, helpers, etc.
When using layouts, you may need to set the -prefix parameter:
git clone https://github.com/sipin/gorazor/
cd gorazor
go build
# The -prefix parameter here tells gorazor the current folder is the base path for github.com/sipin/gorazor.
# So that, when importing "github.com/sipin/gorazor/examples/tpl/layout" in examples/tpl/home.gohtml,
# gorazor will know how to find the layout/helper files.
./gorazor -prefix github.com/sipin/gorazor ./examples/tpl ./examples/tpl
go run examples/main.go
@variable to insert string variable into html template
<div>Hello @user.Name</div>
<div>Hello @strings.ToUpper(req.CurrentUser.Name)</div>
Use raw to skip escaping:
<div>@raw(user.Name)</div>
Only use raw when you are 100% sure what you are doing. Please always be aware of XSS attacks.
@if .... {
....
}
@if .... {
....
} else {
....
}
@for .... {
}
@{
switch .... {
case ....:
<p>...</p>
case 2:
<p>...</p>
default:
<p>...</p>
}
}
Please use example for reference.
Arbitrary go code could be used in templates, like creating a new variable.
@{
username := u.Name
if u.Email != "" {
username += "(" + u.Email + ")"
}
}
<div class="welcome">
<h4>Hello @username</h4>
</div>
It's recommended to keep clean separation of code & view. Please consider move logic into your code before creating a code block in a template.
The first code block in template is strictly for declaration:
like:
@{
import (
"kp/models" //import `"kp/models"` package
"tpl/layout" //import tpl/layout namespace
)
layout := layout.Base //Use layout package's **Base func** for layout
var user *models.User //1st template param
var blog *models.Blog //2nd template param
}
...
first code block must be at the beginning of the template, i.e. before any html.
Any other codes inside the first code block will be ignored.
import must be wrapped in (), import "package_name" is not yet supported.
The variables declared in first code block will be the models of the template, i.e. the parameters of generated function.
If your template doesn't need any model input, then just leave it blank.
As gorazor compiles templates to go function, embedding another template is just calling the generated function, like any other go function.
However, if the templates are designed to be embedded, they must be under helper namespace, i.e. put them in helper sub-folder.
So, using a helper template is similar to:
@if msg != "" {
<div>@helper.ShowMsg(msg)</div>
}
gorazor won't HTML escape the output of helper.XXX.
Please use example for reference.
The syntax for declaring layout is a bit tricky, in the example mentioned above:
@{
import (
"tpl/layout"
)
layout := layout.Base //Use layout package's **base func** for layout
}
"tpl/layout" is the layout package namespace, and the layout variable refers to "layout.Base" func, which should be generated by tpl/layout/base.gohtml.
Must use
layoutas the variable name
layout
gorazor relies on this to determine if a template is for layoutvariable name also must be layoutA layout file tpl/layout/base.gohtml may look like:
@{
var body string
var sidebar string
var footer string
var title string
var css string
var js string
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@title</title>
</head>
<body>
<div class="container">@body</div>
<div class="sidebar">@sidebar</div>
<div class="footer">@footer</div>
@js
</body>
</html>
It's just a usual gorazor template, but:
var body string (As it's always required, maybe we could remove it in future?)layout package, i.e. within "layout" folder.
isLayout := true to declare a template as layoutA template using such layout tpl/index.gohtml may look like:
@{
import (
"tpl/layout"
)
layout := layout.Base
}
@section footer {
<div>Copyright 2014</div>
}
<h2>Welcome to homepage</h2>
It's also possible to use import alias:
@{
import (
share "tpl/layout"
)
layout := share.Base
}
With the page, the page content will be treated as the body section in the layout.
The other section content need to be wrapped with
@section SectionName {
....
}
The template doesn't need to specify all sections defined in the layout. If a section is not specified, it will be considered as "".
Thus, it's possible for the layout to define default section content in such manner:
@{
var body string
var sidebar string
}
<body>
<div class="container">@body</div>
@if sidebar == "" {
<div class="sidebar">I'm the default side bar</div>
} else {
<div class="sidebar">@sidebar</div>
}
</body>
.gohtml..gohtml extension) will be used as the function name in the generated code, with the first letter capitalized (making it exported in Go).helper folder).layout folder).Here is a simple example of gorazor templates and generated Go code.
gorazor via Package Control.gscomplete.py in with this and gslint.py with thisweb-mode supports Razor template engine, so add this into your Emacs config file:
(require 'web-mode)
(add-hook 'web-mode-hook 'my-web-mode-hook)
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.gohtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.js\\'" . web-mode))
(setq web-mode-engines-alist '(("razor" . "\\.gohtml\\'")))
The very first version of gorazor is a hack of razor's port in javascript: vash, thus requires node's to run.
gorazor has been though several rounds of refactoring, and it has completely rewritten in pure Go. Nonetheless, THANK YOU @kirbysayshi for Vash! Without Vash, gorazor may never start.
LICENSE? Well, WTFPL and 996.icu.
Feature completed.
Archived todo
Go
80.1%
Go Template
19.4%