├── .gitignore
├── README.md
├── ace
└── simple.ace
├── amber
└── simple.amber
├── bench.sh
├── ego
├── footer.ego
├── footer.ego.go
├── header.ego
├── header.ego.go
├── index.ego
├── index.ego.go
├── navigation.ego
├── navigation.ego.go
├── simple.ego
└── simple.ego.go
├── ftmpl
├── base.go
├── base.tmpl
├── basecontent.go
├── basecontent.tmpl
├── footer.go
├── footer.tmpl
├── header.go
├── header.tmpl
├── index.go
├── index.tmpl
├── index2.go
├── index2.tmpl
├── navigation.go
├── navigation.tmpl
├── simple.go
└── simple.tmpl
├── go.mod
├── go.sum
├── go
├── includes
│ ├── base.tmpl
│ ├── footer.tmpl
│ ├── header.tmpl
│ └── navigation.tmpl
├── layout
│ └── index.tmpl
└── simple.tmpl
├── goh
├── footer.html
├── footer.html.go
├── header.html
├── header.html.go
├── index.html
├── index.html.go
├── navigation.html
├── navigation.html.go
├── simple.html
└── simple.html.go
├── golang
├── footer.go
├── header.go
├── index.go
├── navigation.go
└── simple.go
├── gomponents
└── simple.go
├── gorazor
├── index.go
├── index.gohtml
├── simple.go
├── simple.gohtml
└── tpl
│ ├── helper
│ ├── footer.go
│ ├── footer.gohtml
│ ├── header.go
│ ├── header.gohtml
│ ├── navigation.go
│ └── navigation.gohtml
│ └── layout
│ ├── base.go
│ └── base.gohtml
├── hero
├── footer.html
├── footer.html.go
├── header.html
├── header.html.go
├── index.html
├── index.html.go
├── navigation.html
├── navigation.html.go
├── simple.html
└── simple.html.go
├── htmlbuilder
└── simple.go
├── jade
├── footer.jade
├── header.jade
├── index.jade
├── index.jade.go
├── jade.go
├── navigation.jade
├── simple.jade
└── simple.jade.go
├── jet
├── blocks.jet
├── index.jet
├── layout.jet
└── simple.jet
├── main.sh
├── model
└── data.go
├── mustache
├── base.mustache
├── footer.mustache
├── header.mustache
├── index.mustache
├── navigation.mustache
└── simple.mustache
├── pongo2
└── simple.pongo
├── quicktemplate
├── footer.qtpl
├── footer.qtpl.go
├── header.qtpl
├── header.qtpl.go
├── index.qtpl
├── index.qtpl.go
├── navigation.qtpl
├── navigation.qtpl.go
├── simple.qtpl
└── simple.qtpl.go
├── raymond
└── simple.handle
├── soy
└── simple.soy
├── templates_complex_test.go
├── templates_test.go
└── templbench
├── footer.templ
├── footer_templ.go
├── header.templ
├── header_templ.go
├── index.templ
├── index_templ.go
├── navigation.templ
├── navigation_templ.go
├── simple.templ
└── simple_templ.go
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor
2 | prof.mem
3 | cpu*.prof
4 | mem*.prof
5 | *.test
6 | files/results*
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # goTemplateBenchmark
2 |
3 | comparing the performance of different template engines
4 |
5 | ## full featured template engines
6 |
7 | - [Ace](https://github.com/yosssi/ace)
8 | - [Amber](https://github.com/eknkc/amber)
9 | - [Go](https://golang.org/pkg/html/template)
10 | - [Handlebars](https://github.com/aymerick/raymond)
11 | - [Mustache](https://github.com/hoisie/mustache)
12 | - [Pongo2](https://github.com/flosch/pongo2)
13 | - [Soy](https://github.com/robfig/soy)
14 | - [Jet](https://github.com/CloudyKit/jet)
15 |
16 | ## precompilation to Go code
17 |
18 | - [ego](https://github.com/benbjohnson/ego)
19 | - [ftmpl](https://github.com/tkrajina/ftmpl)
20 | - [Goh](https://github.com/OblivionOcean/Goh)
21 | - [Gorazor](https://github.com/sipin/gorazor)
22 | - [Quicktemplate](https://github.com/valyala/quicktemplate)
23 | - [Hero](https://github.com/shiyanhui/hero)
24 | - [Jade](https://github.com/Joker/jade)
25 | - [templ](https://github.com/a-h/templ)
26 | - [gomponents](https://github.com/maragudk/gomponents)
27 | - [hb](https://github.com/gouniverse/hb)
28 |
29 | ## baseline benchmarks for comparison
30 |
31 | - DirectBuffer - Use go to write the HTML by hand to the buffer with basic escaping
32 |
33 | ## transpiling to Go Template
34 |
35 | - [Damsel](https://github.com/dskinner/damsel) I won't benchmark transpiling
36 | engines, because transpilation should just happen once at startup. If you
37 | cache the transpilation result, which is recommended, you would have the same
38 | performance numbers as html/template for rendering.
39 |
40 | ## Why?
41 |
42 | Just for fun. Go Templates work nice out of the box and should be used for
43 | rendering from a security point of view. If you care about performance you
44 | should cache the rendered output.
45 |
46 | Sometimes there are templates that cannot be reasonably cached. Then you might
47 | need a really fast template engine with code generation.
48 |
49 | ## How to run the benchmarks
50 |
51 | ```
52 | ./bench.sh -c go
53 | ```
54 |
55 | ## Results dev machine
56 |
57 | local desktop: ryzen 3900x
58 |
59 | ## simple benchmarks
60 | ### full featured template engines
61 | | Name | Runs | µs/op | B/op | allocations/op |
62 | | ---------- | --------- | ------ | ----- | -------------- |
63 | | Ace | 256,797 | 13.017 | 1,121 | 40 |
64 | | Amber | 373,540 | 8.926 | 849 | 36 |
65 | | Golang | 604,209 | 8.650 | 769 | 35 |
66 | | GolangText | 1,426,340 | 2.453 | 128 | 7 |
67 | | Handlebars | 254,118 | 13.904 | 3,424 | 75 |
68 | | JetHTML | 4,334,586 | 0.794 | 0 | 0 |
69 | | Mustache | 810,091 | 4.483 | 1,723 | 30 |
70 | | Pongo2 | 586,269 | 5.805 | 2,075 | 32 |
71 | | Soy | 1,000,000 | 3.545 | 1,224 | 19 |
72 |
73 |
74 | ### precompilation to Go code
75 | | Name | Runs | µs/op | B/op | allocations/op |
76 | | ------------- | ---------- | ----- | ----- | -------------- |
77 | | Ego | 3,287,790 | 1.024 | 85 | 8 |
78 | | Ftmpl | 2,133,676 | 1.704 | 774 | 12 |
79 | | Goh | 41,564,152 | 0.085 | 0 | 0 |
80 | | Gomponents | 630,400 | 5.394 | 1,240 | 64 |
81 | | Gorazor | 4,209,751 | 0.852 | 512 | 5 |
82 | | HB | 735,676 | 4.749 | 1,984 | 36 |
83 | | Hero | 30,954,032 | 0.120 | 0 | 0 |
84 | | Jade | 38,540,751 | 0.083 | 0 | 0 |
85 | | Quicktemplate | 17,429,122 | 0.183 | 0 | 0 |
86 | | Templ | 6,126,406 | 0.575 | 96 | 2 |
87 |
88 |
89 | ## more complex test with template inheritance (if possible)
90 | ### full featured template engines
91 | | Name | Runs | µs/op | B/op | allocations/op |
92 | | ----------------- | ------- | ------ | ----- | -------------- |
93 | | ComplexGolang | 49,784 | 72.503 | 6,565 | 290 |
94 | | ComplexGolangText | 120,789 | 32.198 | 2,236 | 107 |
95 | | ComplexJetHTML | 287,542 | 12.108 | 535 | 5 |
96 | | ComplexMustache | 128,841 | 27.375 | 7,275 | 156 |
97 |
98 |
99 | ### precompilation to Go code
100 | | Name | Runs | µs/op | B/op | allocations/op |
101 | | --------------------- | --------- | ----- | ----- | -------------- |
102 | | ComplexEgo | 1,000,000 | 5.352 | 569 | 31 |
103 | | ComplexFtmpl | 512,026 | 7.545 | 3,536 | 38 |
104 | | ComplexGoDirectBuffer | 6,203,253 | 0.543 | 0 | 0 |
105 | | ComplexGoh | 6,074,386 | 0.569 | 0 | 0 |
106 | | ComplexGorazor | 636,561 | 5.653 | 3,688 | 24 |
107 | | ComplexHero | 3,706,204 | 0.955 | 0 | 0 |
108 | | ComplexJade | 4,795,210 | 0.708 | 0 | 0 |
109 | | ComplexQuicktemplate | 3,466,336 | 1.012 | 0 | 0 |
110 | | ComplexTempl | 1,265,850 | 2.790 | 408 | 11 |
111 |
112 | ## Security
113 |
114 | All packages assume that template authors are trusted. If you allow custom
115 | templates you have to sanitize your user input e.g.
116 | [bluemonday](https://github.com/microcosm-cc/bluemonday). Generally speaking I
117 | would suggest to sanitize every input not just HTML-input.
118 |
119 | ### Attention: This part is not updated since 2016.
120 |
121 | | Framework | Security | Comment |
122 | | ------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
123 | | Ace | No | |
124 | | amber | No | |
125 | | ego | Partial (html.EscapeString) | only HTML, others need to be called manually |
126 | | egon | Partial (html.EscapeString) | only HTML, others need to be called manually |
127 | | egonslinso | Partial (html.EscapeString) | only HTML, others need to be called manually |
128 | | ftmpl | Partial (html.EscapeString) | only HTML, others need to be called manually |
129 | | Go | Yes | contextual escaping [html/template Security Model](https://golang.org/pkg/html/template/#hdr-Security_Model) |
130 | | Gorazor | Partial (template.HTMLEscapeString) | only HTML, others need to be called manually |
131 | | Handlebars | Partial (raymond.escape) | only HTML |
132 | | Hero | Partial (html.EscapeString) | only HTML, others need to be called manually |
133 | | Jade | Partial (html.EscapeString) | Autoescape for HTML, others need to be called manually |
134 | | Jet | Partial (html.EscapeString) | Autoescape for HTML, others need to be called manually |
135 | | Kasia | Partial (kasia.WriteEscapedHtml) | only HTML |
136 | | Mustache | Partial (template.HTMLEscape) | only HTML |
137 | | Pongo2 | Partial (pongo2.filterEscape, pongo2.filterEscapejs) | autoescape only escapes HTML, others could be implemented as pongo filters |
138 | | Quicktemplate | Partial (html.EscapeString) | only HTML, others need to be called manually |
139 | | Soy | Partial (template.HTMLEscapeString, url.QueryEscape, template.JSEscapeString) | autoescape only escapes HTML, contextual escaping is defined as a project goal |
140 |
--------------------------------------------------------------------------------
/ace/simple.ace:
--------------------------------------------------------------------------------
1 | html
2 | body
3 | h1 {{.FirstName}}
4 |
5 | p Here's a list of your favorite colors:
6 | ul
7 | {{range .FavoriteColors }}
8 | li {{.}}
9 | {{ end }}
--------------------------------------------------------------------------------
/amber/simple.amber:
--------------------------------------------------------------------------------
1 | html
2 | body
3 | h1 #{FirstName}
4 |
5 | p Here's a list of your favorite colors:
6 | ul
7 | each $colorName in FavoriteColors
8 | li #{$colorName}
--------------------------------------------------------------------------------
/bench.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # This file:
3 | #
4 | # - Run the benchmarks and output github compatible markdown for the readme.md
5 | #
6 | # Usage:
7 | #
8 | # ./bench.sh
9 | #
10 | # Testing:
11 | # only run the benchmarks
12 | # ./bench.sh -O -F
13 | #
14 | # Based on a template by BASH3 Boilerplate v2.3.0
15 | # http://bash3boilerplate.sh/#authors
16 | #
17 | # The MIT License (MIT)
18 | # Copyright (c) 2013 Kevin van Zonneveld and contributors
19 | # You are not obligated to bundle the LICENSE file with your b3bp projects as long
20 | # as you leave these references intact in the header comments of your source files.
21 |
22 | # shellcheck disable=SC2034
23 | read -r -d '' __usage <<-'EOF' || true # exits non-zero when EOF encountered
24 | -t --time [arg] Benchmark duration. Required. Default="3s"
25 | -c --compare [arg] Old go version binary? Required.
26 | -n --count [arg] Number of runs for comparison. Default=1
27 | -g --go [arg] Curenct go version binary? Required. Default="go"
28 | -B --no-benchmarks Do NOT run the benchmarks.
29 | -F --no-format Do NOT format the results.
30 | -u --update update dependencies.
31 | -v Enable verbose mode, print script as it is executed
32 | -d --debug Enables debug mode
33 | -h --help This page
34 | EOF
35 |
36 | # shellcheck disable=SC2034
37 | read -r -d '' __helptext <<-'EOF' || true # exits non-zero when EOF encountered
38 | This is Bash3 Boilerplate's help text. Feel free to add any description of your
39 | program or elaborate more on command-line arguments. This section is not
40 | parsed and will be added as-is to the help.
41 | EOF
42 |
43 | # shellcheck source=main.sh
44 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/main.sh"
45 |
46 | ### Signal trapping and backtracing
47 | ##############################################################################
48 |
49 | # requires `set -o errtrace`
50 | __b3bp_err_report() {
51 | local error_code=${?}
52 | # shellcheck disable=SC2154
53 | error "Error in ${__file} in function ${1} on line ${2}"
54 | exit ${error_code}
55 | }
56 | # Uncomment the following line for always providing an error backtrace
57 | trap '__b3bp_err_report "${FUNCNAME:-.}" ${LINENO}' ERR
58 |
59 | ### Command-line argument switches (like -d for debugmode, -h for showing helppage)
60 | ##############################################################################
61 |
62 | # debug mode
63 | if [[ "${arg_d:?}" == "1" ]]; then
64 | set -o xtrace
65 | PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
66 | LOG_LEVEL="7"
67 | # Enable error backtracing
68 | trap '__b3bp_err_report "${FUNCNAME:-.}" ${LINENO}' ERR
69 | fi
70 |
71 | # verbose mode
72 | if [[ "${arg_v:?}" == "1" ]]; then
73 | set -o verbose
74 | fi
75 |
76 | # help mode
77 | if [[ "${arg_h:?}" == "1" ]]; then
78 | # Help exists with code 1
79 | help "Help using ${0}"
80 | fi
81 |
82 | __no_benchmarks="false"
83 | if [[ "${arg_B:?}" == "1" ]]; then
84 | __no_benchmarks="true"
85 | fi
86 |
87 | __no_format="false"
88 | if [[ "${arg_F:?}" == "1" ]]; then
89 | __no_format="true"
90 | fi
91 |
92 | ### Validation. Error out if the things required for your script are not present
93 | ##############################################################################
94 |
95 | [[ "${arg_t:-}" ]] || help "Setting benchmark druation with -t or --time is required"
96 | [[ "${arg_c:-}" ]] || help "Setting go versions which will be compared with -c or --compare is required"
97 | [[ "${arg_g:-}" ]] || help "Setting go versions which will be compared with -g or --go is required"
98 | [[ "${LOG_LEVEL:-}" ]] || emergency "Cannot continue without LOG_LEVEL. "
99 |
100 | ### Runtime
101 | ##############################################################################
102 |
103 | info "OSTYPE: ${OSTYPE}"
104 |
105 | info "benchmark duration: ${arg_t}"
106 | info "compare: ${arg_c} to ${arg_g}"
107 | info "count: ${arg_n}"
108 | info "run benchmarks: $([[ "${__no_benchmarks}" == "true" ]] && echo "false" || echo "true")"
109 | info "format output: $([[ "${__no_format}" == "true" ]] && echo "false" || echo "true")"
110 |
111 | # TODO: check if specific go versions are installed, otherise install
112 | # go install golang.org/dl/go1.10.7@latest
113 | # go1.10.7 download
114 |
115 | _updateDeps() {
116 | info "Update dependencies"
117 | go get -u -v ./...
118 |
119 | go install -v github.com/tkrajina/ftmpl@master
120 | ftmpl ftmpl/
121 |
122 | go install -v github.com/sipin/gorazor@main
123 | gorazor -prefix github.com/SlinSo/goTemplateBenchmark gorazor gorazor
124 |
125 | go install -v github.com/valyala/quicktemplate/qtc@master
126 | qtc -dir quicktemplate
127 |
128 | go install -v github.com/benbjohnson/ego/cmd/ego@master
129 | ego ego
130 |
131 | go install -v github.com/shiyanhui/hero/hero@master
132 | hero -source hero/
133 |
134 | # update jade manually
135 | go install -v github.com/Joker/jade/cmd/jade@latest
136 |
137 | jade -d jade/ jade/simple.jade
138 | jade -d jade/ jade/index.jade
139 |
140 | go install github.com/OblivionOcean/Goh@main
141 |
142 | go mod tidy
143 | go test .
144 | }
145 | [[ "${arg_u:?}" == "1" ]] && _updateDeps
146 |
147 | # run old benchmarks
148 | _run_old_benchmarks() {
149 | ${arg_c} test -bench "k(Ace|Amber|Golang|GolangText|Handlebars|Mustache|Pongo2|Soy|JetHTML)$" -benchmem -benchtime="${arg_t}" -count="${arg_n}" | tee ./files/results-1.old
150 | ${arg_c} test -bench "k(Ego|Quicktemplate|Ftmpl|Goh|Gorazor|Hero|Jade|HB|Gomponents|Templ)$" -benchmem -benchtime="${arg_t}" -count="${arg_n}" | tee ./files/results-2.old
151 | ${arg_c} test -bench "Complex(Ace|Amber|Golang|GolangText|Handlebars|Mustache|Pongo2|Soy|JetHTML)$" -benchmem -benchtime="${arg_t}" -count="${arg_n}" | tee ./files/results-3.old
152 | ${arg_c} test -bench "Complex(Ego|Quicktemplate|Ftmpl|Goh|Gorazor|Hero|Jade|Templ|GoDirectBuffer)$" -benchmem -benchtime="${arg_t}" -count="${arg_n}" | tee ./files/results-4.old
153 | }
154 | # [[ "${__no_benchmarks}" == "true" ]] || _run_old_benchmarks
155 |
156 | # run benchmarks
157 | _run_benchmarks() {
158 | ${arg_g} test -bench "k(Ace|Amber|Golang|GolangText|Handlebars|Mustache|Pongo2|Soy|JetHTML)$" -benchmem -benchtime="${arg_t}" -count="${arg_n}" | tee ./files/results-1.new
159 | ${arg_g} test -bench "k(Ego|Quicktemplate|Ftmpl|Goh|Gorazor|Hero|Jade|HB|Gomponents|Templ)$" -benchmem -benchtime="${arg_t}" -count="${arg_n}" | tee ./files/results-2.new
160 | ${arg_g} test -bench "Complex(Ace|Amber|Golang|GolangText|Handlebars|Mustache|Pongo2|Soy|JetHTML)$" -benchmem -benchtime="${arg_t}" -count="${arg_n}" | tee ./files/results-3.new
161 | ${arg_g} test -bench "Complex(Ego|Quicktemplate|Ftmpl|Goh|Gorazor|Hero|Jade|Templ|GoDirectBuffer)$" -benchmem -benchtime="${arg_t}" -count="${arg_n}" | tee ./files/results-4.new
162 | }
163 | [[ "${__no_benchmarks}" == "true" ]] || _run_benchmarks
164 |
165 | # formats a single benchmark
166 | # $1: number of the benchmark
167 | __format_single_benchmark() {
168 | local i=${1}
169 | pb <./files/results-"${i}".new | grep \| | sed '/Name/a \| --- \| --- \| --- \| --- \| --- \|'
170 | echo ""
171 | # echo "\`\`\`"
172 | # echo "comparing: ${arg_c} to ${arg_g}"
173 | # benchstat files/results-"${i}".old files/results-"${i}".new | tee files/results-"${i}"-benchstat.txt
174 | # echo "\`\`\`"
175 | }
176 |
177 | # pretty print for readme.md
178 | _format_benchmarks() {
179 | echo ""
180 | echo "## simple benchmarks"
181 | echo "### full featured template engines"
182 | __format_single_benchmark 1
183 |
184 | echo ""
185 | echo "### precompilation to Go code"
186 | __format_single_benchmark 2
187 |
188 | echo ""
189 | echo "## more complex test with template inheritance (if possible)"
190 | echo "### full featured template engines"
191 | __format_single_benchmark 3
192 |
193 | echo ""
194 | echo "### precompilation to Go code"
195 | __format_single_benchmark 4
196 | }
197 | [[ "${__no_format}" == "true" ]] || _format_benchmarks
198 |
--------------------------------------------------------------------------------
/ego/footer.ego:
--------------------------------------------------------------------------------
1 | <% package ego
2 |
3 | func EgoFooter(w io.Writer) { %>
4 |
5 | <% } %>
--------------------------------------------------------------------------------
/ego/footer.ego.go:
--------------------------------------------------------------------------------
1 | // Generated by ego.
2 | // DO NOT EDIT
3 |
4 | //line ego/footer.ego:1
5 | package ego
6 |
7 | import "fmt"
8 | import "html"
9 | import "io"
10 | import
11 |
12 | //line ego/footer.ego:4
13 | "context"
14 |
15 | func EgoFooter(w io.Writer) {
16 |
17 | _, _ = io.WriteString(w, "\n\n")
18 | //line ego/footer.ego:5
19 | }
20 |
21 | var _ fmt.Stringer
22 | var _ io.Reader
23 | var _ context.Context
24 | var _ = html.EscapeString
25 |
--------------------------------------------------------------------------------
/ego/header.ego:
--------------------------------------------------------------------------------
1 | <% package ego
2 |
3 | func EgoHeader(w io.Writer, title string) { %>
4 | <%= title %>'s Home Page
5 |
6 | <% } %>
--------------------------------------------------------------------------------
/ego/header.ego.go:
--------------------------------------------------------------------------------
1 | // Generated by ego.
2 | // DO NOT EDIT
3 |
4 | //line ego/header.ego:1
5 | package ego
6 |
7 | import "fmt"
8 | import "html"
9 | import "io"
10 | import "context"
11 |
12 | func EgoHeader(w io.Writer, title string) {
13 | //line ego/header.ego:4
14 | _, _ = io.WriteString(w, "\n")
15 | //line ego/header.ego:4
16 | _, _ = io.WriteString(w, html.EscapeString(fmt.Sprint(title)))
17 | //line ego/header.ego:4
18 | _, _ = io.WriteString(w, "'s Home Page\n\n")
19 | //line ego/header.ego:6
20 | }
21 |
22 | var _ fmt.Stringer
23 | var _ io.Reader
24 | var _ context.Context
25 | var _ = html.EscapeString
26 |
--------------------------------------------------------------------------------
/ego/index.ego:
--------------------------------------------------------------------------------
1 | <% package ego
2 | import "github.com/SlinSo/goTemplateBenchmark/model"
3 |
4 | func EgoComplex(w io.Writer, u *model.User, nav []*model.Navigation, title string) { %>
5 |
6 |
7 |
8 |
9 |
10 | <% EgoHeader(w, title) %>
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
Hello <%= u.FirstName %>
21 |
22 |
<%== u.RawContent %>
23 |
<%= u.EscapedContent %>
24 |
25 |
26 | <%
27 | for i := 1; i <= 5; i++ {
28 | if i == 1 { %>
29 |
<%=u.FirstName%> has <%=i%> message
30 | <% } else { %>
31 |
<%=u.FirstName%> has <%=i%> messages
32 | <% }
33 | }
34 | %>
35 |
36 |
37 |
38 |
41 |
42 |
43 |
44 | <% } %>
--------------------------------------------------------------------------------
/ego/index.ego.go:
--------------------------------------------------------------------------------
1 | // Generated by ego.
2 | // DO NOT EDIT
3 |
4 | //line ego/index.ego:1
5 | package ego
6 |
7 | import "fmt"
8 | import "html"
9 | import "io"
10 | import "context"
11 | import "github.com/SlinSo/goTemplateBenchmark/model"
12 |
13 | func EgoComplex(w io.Writer, u *model.User, nav []*model.Navigation, title string) {
14 | //line ego/index.ego:5
15 | _, _ = io.WriteString(w, "\n\n\n\n\n\n")
16 | //line ego/index.ego:10
17 | EgoHeader(w, title)
18 | //line ego/index.ego:11
19 | _, _ = io.WriteString(w, "\n\n\n\n\n\n\n\t
\n\t\t
Hello ")
24 | //line ego/index.ego:20
25 | _, _ = io.WriteString(w, html.EscapeString(fmt.Sprint(u.FirstName)))
26 | //line ego/index.ego:20
27 | _, _ = io.WriteString(w, "
\n\t\t\n\t\t
")
28 | //line ego/index.ego:22
29 | _, _ = fmt.Fprint(w, u.RawContent)
30 | //line ego/index.ego:22
31 | _, _ = io.WriteString(w, "
\n\t\t
")
32 | //line ego/index.ego:23
33 | _, _ = io.WriteString(w, html.EscapeString(fmt.Sprint(u.EscapedContent)))
34 | //line ego/index.ego:23
35 | _, _ = io.WriteString(w, "
\n\t
\n\n")
36 | //line ego/index.ego:26
37 |
38 | for i := 1; i <= 5; i++ {
39 | if i == 1 {
40 | //line ego/index.ego:29
41 | _, _ = io.WriteString(w, "\n\t\t\t
")
42 | //line ego/index.ego:29
43 | _, _ = io.WriteString(w, html.EscapeString(fmt.Sprint(u.FirstName)))
44 | //line ego/index.ego:29
45 | _, _ = io.WriteString(w, " has ")
46 | //line ego/index.ego:29
47 | _, _ = io.WriteString(w, html.EscapeString(fmt.Sprint(i)))
48 | //line ego/index.ego:29
49 | _, _ = io.WriteString(w, " message
\n\t")
50 | //line ego/index.ego:30
51 | } else {
52 | //line ego/index.ego:31
53 | _, _ = io.WriteString(w, "\n\t\t\t
")
54 | //line ego/index.ego:31
55 | _, _ = io.WriteString(w, html.EscapeString(fmt.Sprint(u.FirstName)))
56 | //line ego/index.ego:31
57 | _, _ = io.WriteString(w, " has ")
58 | //line ego/index.ego:31
59 | _, _ = io.WriteString(w, html.EscapeString(fmt.Sprint(i)))
60 | //line ego/index.ego:31
61 | _, _ = io.WriteString(w, " messages
\n\t\t")
62 | //line ego/index.ego:32
63 | }
64 | }
65 |
66 | //line ego/index.ego:35
67 | _, _ = io.WriteString(w, "\n
\n\n\n\n\n\n\n")
72 | //line ego/index.ego:44
73 | }
74 |
75 | var _ fmt.Stringer
76 | var _ io.Reader
77 | var _ context.Context
78 | var _ = html.EscapeString
79 |
--------------------------------------------------------------------------------
/ego/navigation.ego:
--------------------------------------------------------------------------------
1 | <% package ego
2 | import "github.com/SlinSo/goTemplateBenchmark/model"
3 |
4 | func EgoNavigation(w io.Writer, nav []*model.Navigation) { %>
5 |
11 | <% } %>
12 |
--------------------------------------------------------------------------------
/ego/navigation.ego.go:
--------------------------------------------------------------------------------
1 | // Generated by ego.
2 | // DO NOT EDIT
3 |
4 | //line ego/navigation.ego:1
5 | package ego
6 |
7 | import "fmt"
8 | import "html"
9 | import "io"
10 | import "context"
11 | import "github.com/SlinSo/goTemplateBenchmark/model"
12 |
13 | func EgoNavigation(w io.Writer, nav []*model.Navigation) {
14 | //line ego/navigation.ego:5
15 | _, _ = io.WriteString(w, "\n\n")
33 | //line ego/navigation.ego:11
34 | }
35 |
36 | var _ fmt.Stringer
37 | var _ io.Reader
38 | var _ context.Context
39 | var _ = html.EscapeString
40 |
--------------------------------------------------------------------------------
/ego/simple.ego:
--------------------------------------------------------------------------------
1 | <% package ego
2 | import "github.com/SlinSo/goTemplateBenchmark/model"
3 |
4 | func EgoSimple(w io.Writer, u *model.User) { %>
5 |
6 |
7 | <%= u.FirstName %>
8 |
9 | Here's a list of your favorite colors:
10 |
11 | <% for _, colorName := range u.FavoriteColors { %>
12 | - <%= colorName %>
<% } %>
13 |
14 |
15 |
16 | <% } %>
--------------------------------------------------------------------------------
/ego/simple.ego.go:
--------------------------------------------------------------------------------
1 | // Generated by ego.
2 | // DO NOT EDIT
3 |
4 | //line ego/simple.ego:1
5 | package ego
6 |
7 | import "fmt"
8 | import "html"
9 | import "io"
10 | import "context"
11 | import "github.com/SlinSo/goTemplateBenchmark/model"
12 |
13 | func EgoSimple(w io.Writer, u *model.User) {
14 | //line ego/simple.ego:5
15 | _, _ = io.WriteString(w, "\n\n \n ")
16 | //line ego/simple.ego:7
17 | _, _ = io.WriteString(w, html.EscapeString(fmt.Sprint(u.FirstName)))
18 | //line ego/simple.ego:7
19 | _, _ = io.WriteString(w, "
\n\n Here's a list of your favorite colors:
\n \n ")
20 | //line ego/simple.ego:11
21 | for _, colorName := range u.FavoriteColors {
22 | //line ego/simple.ego:12
23 | _, _ = io.WriteString(w, "\n - ")
24 | //line ego/simple.ego:12
25 | _, _ = io.WriteString(w, html.EscapeString(fmt.Sprint(colorName)))
26 | //line ego/simple.ego:12
27 | _, _ = io.WriteString(w, "
")
28 | //line ego/simple.ego:12
29 | }
30 | //line ego/simple.ego:13
31 | _, _ = io.WriteString(w, "\n
\n \n\n")
32 | //line ego/simple.ego:16
33 | }
34 |
35 | var _ fmt.Stringer
36 | var _ io.Reader
37 | var _ context.Context
38 | var _ = html.EscapeString
39 |
--------------------------------------------------------------------------------
/ftmpl/base.go:
--------------------------------------------------------------------------------
1 | // Package ftmpl is generated with ftmpl {{{v0.3.1}}}, do not edit!!!! */
2 | package ftmpl
3 |
4 | import (
5 | "bytes"
6 | "errors"
7 | "fmt"
8 | "github.com/SlinSo/goTemplateBenchmark/model"
9 | "html"
10 | "os"
11 | )
12 |
13 | func init() {
14 | _ = fmt.Sprintf
15 | _ = errors.New
16 | _ = os.Stderr
17 | _ = html.EscapeString
18 | }
19 |
20 | // TMPLERRbase evaluates a template base.tmpl
21 | func TMPLERRbase(u *model.User, nav []*model.Navigation, title string) (string, error) {
22 | _template := "base.tmpl"
23 | _escape := html.EscapeString
24 | var _ftmpl bytes.Buffer
25 | _w := func(str string) { _, _ = _ftmpl.WriteString(str) }
26 | _, _, _ = _template, _escape, _w
27 |
28 | _w(`
29 |
30 |
31 |
32 |
35 |
36 |
39 |
40 |
43 |
44 |
47 |
48 |
49 | `)
50 |
51 | return _ftmpl.String(), nil
52 | }
53 |
54 | // TMPLbase evaluates a template base.tmpl
55 | func TMPLbase(u *model.User, nav []*model.Navigation, title string) string {
56 | html, err := TMPLERRbase(u, nav, title)
57 | if err != nil {
58 | _, _ = os.Stderr.WriteString("Error running template base.tmpl:" + err.Error())
59 | }
60 | return html
61 | }
62 |
--------------------------------------------------------------------------------
/ftmpl/base.tmpl:
--------------------------------------------------------------------------------
1 | !#import "github.com/SlinSo/goTemplateBenchmark/model"
2 | !#arg u *model.User
3 | !#arg nav []*model.Navigation
4 | !#arg title string
5 |
6 |
7 |
8 |
9 |
10 | !#include header
11 |
12 |
13 |
16 |
17 |
20 |
21 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/ftmpl/basecontent.go:
--------------------------------------------------------------------------------
1 | // Package ftmpl is generated with ftmpl {{{v0.3.1}}}, do not edit!!!! */
2 | package ftmpl
3 |
4 | import (
5 | "bytes"
6 | "errors"
7 | "fmt"
8 | "github.com/SlinSo/goTemplateBenchmark/model"
9 | "html"
10 | "os"
11 | )
12 |
13 | func init() {
14 | _ = fmt.Sprintf
15 | _ = errors.New
16 | _ = os.Stderr
17 | _ = html.EscapeString
18 | }
19 |
20 | // TMPLERRbasecontent evaluates a template basecontent.tmpl
21 | func TMPLERRbasecontent(u *model.User, nav []*model.Navigation, title string) (string, error) {
22 | _template := "basecontent.tmpl"
23 | _escape := html.EscapeString
24 | var _ftmpl bytes.Buffer
25 | _w := func(str string) { _, _ = _ftmpl.WriteString(str) }
26 | _, _, _ = _template, _escape, _w
27 |
28 | _w(`
29 | `)
30 | _w(`
31 |
32 |
33 |
34 |
35 | `)
36 | _w(``)
37 | _w(fmt.Sprintf(`%s`, _escape(title)))
38 | _w(`'s Home Page
39 |
40 |
41 | `)
42 | _w(`
43 |
44 |
60 |
61 |
64 |
65 |
71 |
72 |
73 | `)
74 |
75 | return _ftmpl.String(), nil
76 | }
77 |
78 | // TMPLbasecontent evaluates a template basecontent.tmpl
79 | func TMPLbasecontent(u *model.User, nav []*model.Navigation, title string) string {
80 | html, err := TMPLERRbasecontent(u, nav, title)
81 | if err != nil {
82 | _, _ = os.Stderr.WriteString("Error running template basecontent.tmpl:" + err.Error())
83 | }
84 | return html
85 | }
86 |
--------------------------------------------------------------------------------
/ftmpl/basecontent.tmpl:
--------------------------------------------------------------------------------
1 | !#extends base
2 |
3 | !#sub header
4 | !#arg title string
5 | {{s title}}'s Home Page
6 |
7 |
8 | !#sub footer
9 |
10 |
11 | !#sub navigation
12 | !#import "github.com/SlinSo/goTemplateBenchmark/model"
13 | !#arg nav []*model.Navigation
14 |
--------------------------------------------------------------------------------
/ftmpl/footer.go:
--------------------------------------------------------------------------------
1 | // Package ftmpl is generated with ftmpl {{{v0.3.1}}}, do not edit!!!! */
2 | package ftmpl
3 |
4 | import (
5 | "bytes"
6 | "errors"
7 | "fmt"
8 | "html"
9 | "os"
10 | )
11 |
12 | func init() {
13 | _ = fmt.Sprintf
14 | _ = errors.New
15 | _ = os.Stderr
16 | _ = html.EscapeString
17 | }
18 |
19 | // TMPLERRfooter evaluates a template footer.tmpl
20 | func TMPLERRfooter() (string, error) {
21 | _template := "footer.tmpl"
22 | _escape := html.EscapeString
23 | var _ftmpl bytes.Buffer
24 | _w := func(str string) { _, _ = _ftmpl.WriteString(str) }
25 | _, _, _ = _template, _escape, _w
26 |
27 | _w(``)
28 |
29 | return _ftmpl.String(), nil
30 | }
31 |
32 | // TMPLfooter evaluates a template footer.tmpl
33 | func TMPLfooter() string {
34 | html, err := TMPLERRfooter()
35 | if err != nil {
36 | _, _ = os.Stderr.WriteString("Error running template footer.tmpl:" + err.Error())
37 | }
38 | return html
39 | }
40 |
--------------------------------------------------------------------------------
/ftmpl/footer.tmpl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ftmpl/header.go:
--------------------------------------------------------------------------------
1 | // Package ftmpl is generated with ftmpl {{{v0.3.1}}}, do not edit!!!! */
2 | package ftmpl
3 |
4 | import (
5 | "bytes"
6 | "errors"
7 | "fmt"
8 | "html"
9 | "os"
10 | )
11 |
12 | func init() {
13 | _ = fmt.Sprintf
14 | _ = errors.New
15 | _ = os.Stderr
16 | _ = html.EscapeString
17 | }
18 |
19 | // TMPLERRheader evaluates a template header.tmpl
20 | func TMPLERRheader(title string) (string, error) {
21 | _template := "header.tmpl"
22 | _escape := html.EscapeString
23 | var _ftmpl bytes.Buffer
24 | _w := func(str string) { _, _ = _ftmpl.WriteString(str) }
25 | _, _, _ = _template, _escape, _w
26 |
27 | _w(``)
28 | _w(fmt.Sprintf(`%s`, _escape(title)))
29 | _w(`'s Home Page
30 | `)
31 |
32 | return _ftmpl.String(), nil
33 | }
34 |
35 | // TMPLheader evaluates a template header.tmpl
36 | func TMPLheader(title string) string {
37 | html, err := TMPLERRheader(title)
38 | if err != nil {
39 | _, _ = os.Stderr.WriteString("Error running template header.tmpl:" + err.Error())
40 | }
41 | return html
42 | }
43 |
--------------------------------------------------------------------------------
/ftmpl/header.tmpl:
--------------------------------------------------------------------------------
1 | !#arg title string
2 | {{s title}}'s Home Page
3 |
--------------------------------------------------------------------------------
/ftmpl/index.go:
--------------------------------------------------------------------------------
1 | // Package ftmpl is generated with ftmpl {{{v0.3.1}}}, do not edit!!!! */
2 | package ftmpl
3 |
4 | import (
5 | "bytes"
6 | "errors"
7 | "fmt"
8 | "github.com/SlinSo/goTemplateBenchmark/model"
9 | "html"
10 | "os"
11 | )
12 |
13 | func init() {
14 | _ = fmt.Sprintf
15 | _ = errors.New
16 | _ = os.Stderr
17 | _ = html.EscapeString
18 | }
19 |
20 | // TMPLERRindex evaluates a template index.tmpl
21 | func TMPLERRindex(u *model.User, nav []*model.Navigation, title string) (string, error) {
22 | _template := "index.tmpl"
23 | _escape := html.EscapeString
24 | var _ftmpl bytes.Buffer
25 | _w := func(str string) { _, _ = _ftmpl.WriteString(str) }
26 | _, _, _ = _template, _escape, _w
27 |
28 | _w(`
29 | `)
30 | _w(`
31 |
32 |
33 |
34 |
35 | `)
36 | _w(``)
37 | _w(fmt.Sprintf(`%s`, _escape(title)))
38 | _w(`'s Home Page
39 |
40 |
41 | `)
42 | _w(`
43 |
44 |
62 |
63 |
64 | `)
65 | _w(`
66 |
67 |
Hello `)
68 | _w(fmt.Sprintf(`%s`, _escape(u.FirstName)))
69 | _w(`
70 |
71 |
`)
72 | _w(fmt.Sprintf(`%s`, u.RawContent))
73 | _w(`
74 |
`)
75 | _w(fmt.Sprintf(`%s`, _escape(u.EscapedContent)))
76 | _w(`
77 |
78 |
79 |
80 | `)
81 | for i := 1; i <= 5; i++ {
82 | if i == 1 {
83 | _w(`
`)
84 | _w(fmt.Sprintf(`%s`, _escape(u.FirstName)))
85 | _w(` has `)
86 | _w(fmt.Sprintf(`%d`, i))
87 | _w(` message
88 | `)
89 | } else {
90 | _w(`
`)
91 | _w(fmt.Sprintf(`%s`, _escape(u.FirstName)))
92 | _w(` has `)
93 | _w(fmt.Sprintf(`%d`, i))
94 | _w(` messages
95 | `)
96 | }
97 | }
98 | _w(`
99 | `)
100 | _w(`
101 |
102 |
108 |
109 |
110 | `)
111 |
112 | return _ftmpl.String(), nil
113 | }
114 |
115 | // TMPLindex evaluates a template index.tmpl
116 | func TMPLindex(u *model.User, nav []*model.Navigation, title string) string {
117 | html, err := TMPLERRindex(u, nav, title)
118 | if err != nil {
119 | _, _ = os.Stderr.WriteString("Error running template index.tmpl:" + err.Error())
120 | }
121 | return html
122 | }
123 |
--------------------------------------------------------------------------------
/ftmpl/index.tmpl:
--------------------------------------------------------------------------------
1 | !#extends base
2 |
3 | !#sub header
4 | {{s title}}'s Home Page
5 |
6 |
7 | !#sub footer
8 |
9 |
10 | !#sub navigation
11 |
16 |
17 | !#sub body
18 |
19 |
20 |
Hello {{s u.FirstName }}
21 |
22 |
{{=s u.RawContent }}
23 |
{{s u.EscapedContent }}
24 |
25 |
26 |
27 | ! for i := 1; i <= 5; i++ {
28 | ! if i == 1 {
29 |
{{s u.FirstName}} has {{d i}} message
30 | ! } else {
31 |
{{s u.FirstName}} has {{d i}} messages
32 | ! }
33 | ! }
34 |
35 |
--------------------------------------------------------------------------------
/ftmpl/index2.go:
--------------------------------------------------------------------------------
1 | // Package ftmpl is generated with ftmpl {{{v0.3.1}}}, do not edit!!!! */
2 | package ftmpl
3 |
4 | import (
5 | "bytes"
6 | "errors"
7 | "fmt"
8 | "github.com/SlinSo/goTemplateBenchmark/model"
9 | "html"
10 | "os"
11 | )
12 |
13 | func init() {
14 | _ = fmt.Sprintf
15 | _ = errors.New
16 | _ = os.Stderr
17 | _ = html.EscapeString
18 | }
19 |
20 | // TMPLERRindex2 evaluates a template index2.tmpl
21 | func TMPLERRindex2(u *model.User, nav []*model.Navigation, title string) (string, error) {
22 | _template := "index2.tmpl"
23 | _escape := html.EscapeString
24 | var _ftmpl bytes.Buffer
25 | _w := func(str string) { _, _ = _ftmpl.WriteString(str) }
26 | _, _, _ = _template, _escape, _w
27 |
28 | _w(`
29 | `)
30 | _w(`
31 |
32 |
33 |
34 |
35 | `)
36 | _w(``)
37 | _w(fmt.Sprintf(`%s`, _escape(title)))
38 | _w(`'s Home Page
39 | `)
40 | _w(`
41 |
42 | `)
43 | _w(`
44 |
45 |
64 |
65 |
66 | `)
67 | _w(`
68 |
69 |
Hello `)
70 | _w(fmt.Sprintf(`%s`, _escape(u.FirstName)))
71 | _w(`
72 |
73 |
`)
74 | _w(fmt.Sprintf(`%s`, u.RawContent))
75 | _w(`
76 |
`)
77 | _w(fmt.Sprintf(`%s`, _escape(u.EscapedContent)))
78 | _w(`
79 |
80 |
81 |
82 | `)
83 | for i := 1; i <= 5; i++ {
84 | if i == 1 {
85 | _w(`
`)
86 | _w(fmt.Sprintf(`%s`, _escape(u.FirstName)))
87 | _w(` has `)
88 | _w(fmt.Sprintf(`%d`, i))
89 | _w(` message
90 | `)
91 | } else {
92 | _w(`
`)
93 | _w(fmt.Sprintf(`%s`, _escape(u.FirstName)))
94 | _w(` has `)
95 | _w(fmt.Sprintf(`%d`, i))
96 | _w(` messages
97 | `)
98 | }
99 | }
100 | _w(`
101 | `)
102 | _w(`
103 |
104 |
111 |
112 |
113 | `)
114 |
115 | return _ftmpl.String(), nil
116 | }
117 |
118 | // TMPLindex2 evaluates a template index2.tmpl
119 | func TMPLindex2(u *model.User, nav []*model.Navigation, title string) string {
120 | html, err := TMPLERRindex2(u, nav, title)
121 | if err != nil {
122 | _, _ = os.Stderr.WriteString("Error running template index2.tmpl:" + err.Error())
123 | }
124 | return html
125 | }
126 |
--------------------------------------------------------------------------------
/ftmpl/index2.tmpl:
--------------------------------------------------------------------------------
1 | !#extends base
2 |
3 | !#sub header
4 | {{!#insert "header.tmpl" }}
5 |
6 | !#sub footer
7 | {{!#insert "footer.tmpl" }}
8 |
9 | !#sub navigation
10 | {{!#insert "navigation.tmpl" }}
11 |
12 | !#sub body
13 |
14 |
15 |
Hello {{s u.FirstName }}
16 |
17 |
{{=s u.RawContent }}
18 |
{{s u.EscapedContent }}
19 |
20 |
21 |
22 | ! for i := 1; i <= 5; i++ {
23 | ! if i == 1 {
24 |
{{s u.FirstName}} has {{d i}} message
25 | ! } else {
26 |
{{s u.FirstName}} has {{d i}} messages
27 | ! }
28 | ! }
29 |
30 |
--------------------------------------------------------------------------------
/ftmpl/navigation.go:
--------------------------------------------------------------------------------
1 | // Package ftmpl is generated with ftmpl {{{v0.3.1}}}, do not edit!!!! */
2 | package ftmpl
3 |
4 | import (
5 | "bytes"
6 | "errors"
7 | "fmt"
8 | "github.com/SlinSo/goTemplateBenchmark/model"
9 | "html"
10 | "os"
11 | )
12 |
13 | func init() {
14 | _ = fmt.Sprintf
15 | _ = errors.New
16 | _ = os.Stderr
17 | _ = html.EscapeString
18 | }
19 |
20 | // TMPLERRnavigation evaluates a template navigation.tmpl
21 | func TMPLERRnavigation(nav []*model.Navigation) (string, error) {
22 | _template := "navigation.tmpl"
23 | _escape := html.EscapeString
24 | var _ftmpl bytes.Buffer
25 | _w := func(str string) { _, _ = _ftmpl.WriteString(str) }
26 | _, _, _ = _template, _escape, _w
27 |
28 | _w(``)
41 |
42 | return _ftmpl.String(), nil
43 | }
44 |
45 | // TMPLnavigation evaluates a template navigation.tmpl
46 | func TMPLnavigation(nav []*model.Navigation) string {
47 | html, err := TMPLERRnavigation(nav)
48 | if err != nil {
49 | _, _ = os.Stderr.WriteString("Error running template navigation.tmpl:" + err.Error())
50 | }
51 | return html
52 | }
53 |
--------------------------------------------------------------------------------
/ftmpl/navigation.tmpl:
--------------------------------------------------------------------------------
1 | !#import "github.com/SlinSo/goTemplateBenchmark/model"
2 | !#arg nav []*model.Navigation
3 |
--------------------------------------------------------------------------------
/ftmpl/simple.go:
--------------------------------------------------------------------------------
1 | // Package ftmpl is generated with ftmpl {{{v0.3.1}}}, do not edit!!!! */
2 | package ftmpl
3 |
4 | import (
5 | "bytes"
6 | "errors"
7 | "fmt"
8 | "github.com/SlinSo/goTemplateBenchmark/model"
9 | "html"
10 | "os"
11 | )
12 |
13 | func init() {
14 | _ = fmt.Sprintf
15 | _ = errors.New
16 | _ = os.Stderr
17 | _ = html.EscapeString
18 | }
19 |
20 | // TMPLERRsimple evaluates a template simple.tmpl
21 | func TMPLERRsimple(u *model.User) (string, error) {
22 | _template := "simple.tmpl"
23 | _escape := html.EscapeString
24 | var _ftmpl bytes.Buffer
25 | _w := func(str string) { _, _ = _ftmpl.WriteString(str) }
26 | _, _, _ = _template, _escape, _w
27 |
28 | _w(`
29 |
30 | `)
31 | _w(fmt.Sprintf(`%s`, _escape(u.FirstName)))
32 | _w(`
33 |
34 | Here's a list of your favorite colors:
35 |
36 | `)
37 | for _, colorName := range u.FavoriteColors {
38 | _w(`
39 | - `)
40 | _w(fmt.Sprintf(`%s`, _escape(colorName)))
41 | _w(`
`)
42 | }
43 | _w(`
44 |
45 |
46 | `)
47 |
48 | return _ftmpl.String(), nil
49 | }
50 |
51 | // TMPLsimple evaluates a template simple.tmpl
52 | func TMPLsimple(u *model.User) string {
53 | html, err := TMPLERRsimple(u)
54 | if err != nil {
55 | _, _ = os.Stderr.WriteString("Error running template simple.tmpl:" + err.Error())
56 | }
57 | return html
58 | }
59 |
--------------------------------------------------------------------------------
/ftmpl/simple.tmpl:
--------------------------------------------------------------------------------
1 | !#import "github.com/SlinSo/goTemplateBenchmark/model"
2 | !#arg u *model.User
3 |
4 |
5 | {{s u.FirstName }}
6 |
7 | Here's a list of your favorite colors:
8 |
9 | {{! for _, colorName := range u.FavoriteColors }}
10 | - {{s colorName }}
{{! end }}
11 |
12 |
13 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/SlinSo/goTemplateBenchmark
2 |
3 | go 1.23.0
4 |
5 | toolchain go1.23.6
6 |
7 | require (
8 | github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible
9 | github.com/OblivionOcean/Goh v1.0.3
10 | github.com/a-h/templ v0.3.833
11 | github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible
12 | github.com/dchest/htmlmin v1.2.0
13 | github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385
14 | github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3
15 | github.com/gouniverse/hb v1.83.3
16 | github.com/hoisie/mustache v0.0.0-20160804235033-6375acf62c69
17 | github.com/robfig/soy v0.0.0-20210708182426-5db4016fcbab
18 | github.com/shiyanhui/hero v0.0.2
19 | github.com/sipin/gorazor v1.2.2
20 | github.com/valyala/bytebufferpool v1.0.1-0.20180905182247-cdfbe9377474
21 | github.com/valyala/quicktemplate v1.8.0
22 | github.com/yosssi/ace v0.0.5
23 | maragu.dev/gomponents v1.0.0
24 | )
25 |
26 | require (
27 | github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
28 | github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc // indirect
29 | github.com/dchest/jsmin v0.0.0-20220218165748-59f39799265f // indirect
30 | github.com/fsnotify/fsnotify v1.7.0 // indirect
31 | github.com/kr/text v0.2.0 // indirect
32 | github.com/robertkrimen/otto v0.0.0-20210614181706-373ff5438452 // indirect
33 | github.com/robfig/gettext v0.0.0-20210319194541-81dadf19848b // indirect
34 | golang.org/x/net v0.34.0 // indirect
35 | golang.org/x/sys v0.29.0 // indirect
36 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
37 | gopkg.in/yaml.v2 v2.4.0 // indirect
38 | )
39 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c=
2 | github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
3 | github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible h1:rZgFj+Gtf3NMi/U5FvCvhzaxzW/TaPYgUYx3bAPz9DE=
4 | github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w=
5 | github.com/OblivionOcean/Goh v1.0.3 h1:qLxX2bhYBUV47jixxVrSKuqjGfzThkMcPYq/58w28DQ=
6 | github.com/OblivionOcean/Goh v1.0.3/go.mod h1:FRmIA1vHrY9KeF5RHIJ+XtLcPurq4C6xtFMs3RAmm9c=
7 | github.com/a-h/templ v0.3.833 h1:L/KOk/0VvVTBegtE0fp2RJQiBm7/52Zxv5fqlEHiQUU=
8 | github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk=
9 | github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
10 | github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible h1:Ppm0npCCsmuR9oQaBtRuZcmILVE74aXE+AmrJj8L2ns=
11 | github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
12 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
13 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
14 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
15 | github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc h1:VBS1z48BFEe00G81z8MKOtwX7f/ISkuH38NscT8iVPw=
16 | github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc/go.mod h1:ABJPuor7YlcsHmvJ1QxX38e2NcufLY3hm0yXv+cy9sI=
17 | github.com/dchest/htmlmin v1.2.0 h1:0IC9DqQj2riphSYNlrSxwgBr8q5Qx81Dj0/GSHo9hus=
18 | github.com/dchest/htmlmin v1.2.0/go.mod h1:QylviOfB3doepxYcCxvu71oZe98jP0SrO5iiWKGvHxo=
19 | github.com/dchest/jsmin v0.0.0-20220218165748-59f39799265f h1:OGqDDftRTwrvUoL6pOG7rYTmWsTCvyEWFsMjg+HcOaA=
20 | github.com/dchest/jsmin v0.0.0-20220218165748-59f39799265f/go.mod h1:Dv9D0NUlAsaQcGQZa5kc5mqR9ua72SmA8VXi4cd+cBw=
21 | github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o=
22 | github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
23 | github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3 h1:fmFk0Wt3bBxxwZnu48jqMdaOR/IZ4vdtJFuaFV8MpIE=
24 | github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3/go.mod h1:bJWSKrZyQvfTnb2OudyUjurSG4/edverV7n82+K3JiM=
25 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
26 | github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
27 | github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
28 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
29 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
30 | github.com/gouniverse/hb v1.83.3 h1:26hEkS6/Hul8PkzgH8JZnQvFI/aWx7DuT3MFdgmjI/w=
31 | github.com/gouniverse/hb v1.83.3/go.mod h1:WDUCGoptHp/fAYT634lQ2846sGx88yXOOWMvlEaezYM=
32 | github.com/hoisie/mustache v0.0.0-20160804235033-6375acf62c69 h1:umaj0TCQ9lWUUKy2DxAhEzPbwd0jnxiw1EI2z3FiILM=
33 | github.com/hoisie/mustache v0.0.0-20160804235033-6375acf62c69/go.mod h1:zdLK9ilQRSMjSeLKoZ4BqUfBT7jswTGF8zRlKEsiRXA=
34 | github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
35 | github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
36 | github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
37 | github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
38 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
39 | github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
40 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
41 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
42 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
43 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
44 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
45 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
46 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
47 | github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
48 | github.com/robertkrimen/otto v0.0.0-20210614181706-373ff5438452 h1:ewTtJ72GFy2e0e8uyiDwMG3pKCS5mBh+hdSTYsPKEP8=
49 | github.com/robertkrimen/otto v0.0.0-20210614181706-373ff5438452/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
50 | github.com/robfig/gettext v0.0.0-20200526193151-a093425df149/go.mod h1:5KSZdCir8kQ33UwFOeBzxIXDVCb7ine4/iCMiJ9D1oQ=
51 | github.com/robfig/gettext v0.0.0-20210319194541-81dadf19848b h1:V1N1ZQEzu4ell92Avbw+KVlmfaQo60UvGAF0Z+tfRMo=
52 | github.com/robfig/gettext v0.0.0-20210319194541-81dadf19848b/go.mod h1:5KSZdCir8kQ33UwFOeBzxIXDVCb7ine4/iCMiJ9D1oQ=
53 | github.com/robfig/soy v0.0.0-20210708182426-5db4016fcbab h1:TlVjS8Eu05dVtQRiykqPE8G+Zm3752JpvOWE122eXEg=
54 | github.com/robfig/soy v0.0.0-20210708182426-5db4016fcbab/go.mod h1:VTQjKFKmnjdLvj+6scw5cZb/z7TCcEhk/THXjTDTrUc=
55 | github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
56 | github.com/shiyanhui/hero v0.0.2 h1:RF8fwiIeWbVsdki8LCS905pxLjCQbOz/NcKE0g1ZOJc=
57 | github.com/shiyanhui/hero v0.0.2/go.mod h1:aBlyf5bmklQfvOmVQm5i04lIGFY7t2QYIJdqEMNGJZM=
58 | github.com/sipin/gorazor v1.2.2 h1:iAsGoBVNakC0VaMS+izk9YFPK5dzTtL5TZ4Q9fLDqYE=
59 | github.com/sipin/gorazor v1.2.2/go.mod h1:IjfAnNow6XFn9MAVnwvy7QqUQPPtJM7jz0WREmdgktU=
60 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
61 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
62 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
63 | github.com/valyala/bytebufferpool v1.0.1-0.20180905182247-cdfbe9377474 h1:5x9cPAJaXVu7KpYQ5rcHWufoM4BK2e+3EbNv24URpbk=
64 | github.com/valyala/bytebufferpool v1.0.1-0.20180905182247-cdfbe9377474/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
65 | github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
66 | github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
67 | github.com/valyala/quicktemplate v1.8.0 h1:zU0tjbIqTRgKQzFY1L42zq0qR3eh4WoQQdIdqCysW5k=
68 | github.com/valyala/quicktemplate v1.8.0/go.mod h1:qIqW8/igXt8fdrUln5kOSb+KWMaJ4Y8QUsfd1k6L2jM=
69 | github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
70 | github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA=
71 | github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0=
72 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
73 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
74 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
75 | golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
76 | golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
77 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
78 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
79 | golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
80 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
81 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
82 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
83 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
84 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
85 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
86 | golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
87 | golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
88 | golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
89 | golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
90 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
91 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
92 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
93 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
94 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
95 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
96 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
97 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
98 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
99 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
100 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
101 | golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
102 | golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
103 | golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
104 | golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
105 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
106 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
107 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
108 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
109 | golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
110 | golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
111 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
112 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
113 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
114 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
115 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
116 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
117 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
118 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
119 | golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
120 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
121 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
122 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
123 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
124 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
125 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
126 | gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
127 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
128 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
129 | gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
130 | gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
131 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
132 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
133 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
134 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
135 | maragu.dev/gomponents v1.0.0 h1:eeLScjq4PqP1l+r5z/GC+xXZhLHXa6RWUWGW7gSfLh4=
136 | maragu.dev/gomponents v1.0.0/go.mod h1:oEDahza2gZoXDoDHhw8jBNgH+3UR5ni7Ur648HORydM=
137 |
--------------------------------------------------------------------------------
/go/includes/base.tmpl:
--------------------------------------------------------------------------------
1 | {{ define "base" }}
2 |
3 |
4 |
5 |
6 |
7 | {{ template "header" . }}
8 |
9 |
10 |
13 |
14 |
15 | {{ template "content" .}}
16 |
17 |
18 |
21 |
22 |
23 |
24 | {{end}}
--------------------------------------------------------------------------------
/go/includes/footer.tmpl:
--------------------------------------------------------------------------------
1 | {{ define "footer" }}
2 |
3 | {{ end }}
--------------------------------------------------------------------------------
/go/includes/header.tmpl:
--------------------------------------------------------------------------------
1 | {{ define "header" }}
2 | {{ .Title }}'s Home Page
3 |
4 | {{ end }}
--------------------------------------------------------------------------------
/go/includes/navigation.tmpl:
--------------------------------------------------------------------------------
1 | {{ define "navigation" }}
2 |
3 | {{ range .Nav }}
4 | - {{.Item}}
5 | {{end}}
6 |
7 | {{ end }}
--------------------------------------------------------------------------------
/go/layout/index.tmpl:
--------------------------------------------------------------------------------
1 | {{ define "title"}}{{ .u.FirstName }}{{ end }}
2 | {{ define "content" }}
3 |
4 |
5 |
6 |
Hello {{ .User.FirstName }}
7 |
8 |
{{ .User.RawContent |safehtml}}
9 |
{{ .User.EscapedContent }}
10 |
11 | {{range .Messages}}
12 | {{if eq .I 1}}
13 |
{{ $.User.FirstName}} has {{ .I }} message
14 | {{else}}
15 |
{{ $.User.FirstName}} has {{ .I }} messages
16 | {{end}}
17 | {{end}}
18 |
19 | {{ end }}
--------------------------------------------------------------------------------
/go/simple.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ .FirstName }}
4 |
5 | Here's a list of your favorite colors:
6 |
7 | {{ range .FavoriteColors }}
8 | - {{ . }}
{{ end }}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/goh/footer.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/goh/footer.html.go:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT!
2 | // Generate By Goh
3 |
4 | package template
5 |
--------------------------------------------------------------------------------
/goh/header.html:
--------------------------------------------------------------------------------
1 | <%= title %>'s Home Page
2 |
3 |
--------------------------------------------------------------------------------
/goh/header.html.go:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT!
2 | // Generate By Goh
3 |
4 | package template
5 |
--------------------------------------------------------------------------------
/goh/index.html:
--------------------------------------------------------------------------------
1 | <%: func Index(u *model.User, nav []*model.Navigation, title string, buffer *bytes.Buffer) %>
2 |
3 | <%!
4 | import "github.com/SlinSo/goTemplateBenchmark/model"
5 | %>
6 |
7 |
8 |
9 |
10 |
11 |
12 | <%+ "header.html" %>
13 |
14 |
15 |
18 |
19 |
20 |
21 |
22 |
Hello <%= u.FirstName %>
23 |
24 |
<%== u.RawContent %>
25 |
<%= u.EscapedContent %>
26 |
27 |
28 | <% for i := 1; i <= 5; i++ { %>
29 | <% if i == 1 { %>
30 |
<%= u.FirstName %> has <%=i i %> message
31 | <% } else { %>
32 |
<%= u.FirstName %> has <%=i i %> messages
33 | <% } %>
34 | <% } %>
35 |
36 |
37 |
38 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/goh/index.html.go:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT!
2 | // Generate By Goh
3 |
4 | package template
5 |
6 | import (
7 | "bytes"
8 |
9 | Goh "github.com/OblivionOcean/Goh/utils"
10 | "github.com/SlinSo/goTemplateBenchmark/model"
11 | )
12 |
13 | func Index(u *model.User, nav []*model.Navigation, title string, buffer *bytes.Buffer) {
14 | buffer.Grow(543)
15 | buffer.WriteString(`
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | `)
25 | Goh.EscapeHTML(title, buffer)
26 | buffer.WriteString(`'s Home Page
27 |
28 |
29 |
30 |
31 |
47 |
48 |
49 |
50 |
51 |
Hello `)
52 | Goh.EscapeHTML(u.FirstName, buffer)
53 | buffer.WriteString(`
54 |
55 |
`)
56 | buffer.WriteString(u.RawContent)
57 | buffer.WriteString(`
58 |
`)
59 | Goh.EscapeHTML(u.EscapedContent, buffer)
60 | buffer.WriteString(`
61 |
62 |
63 | `)
64 | for i := 1; i <= 5; i++ {
65 | buffer.WriteString(`
66 | `)
67 | if i == 1 {
68 | buffer.WriteString(`
69 |
`)
70 | Goh.EscapeHTML(u.FirstName, buffer)
71 | buffer.WriteString(` has `)
72 | Goh.FormatInt(int64(i), buffer)
73 | buffer.WriteString(` message
74 | `)
75 | } else {
76 | buffer.WriteString(`
77 |
`)
78 | Goh.EscapeHTML(u.FirstName, buffer)
79 | buffer.WriteString(` has `)
80 | Goh.FormatInt(int64(i), buffer)
81 | buffer.WriteString(` messages
82 | `)
83 | }
84 | buffer.WriteString(`
85 | `)
86 | }
87 | buffer.WriteString(`
88 |
89 |
90 |
91 |
95 |
96 |
97 |
98 | `)
99 | }
100 |
--------------------------------------------------------------------------------
/goh/navigation.html:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/goh/navigation.html.go:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT!
2 | // Generate By Goh
3 |
4 | package template
5 |
--------------------------------------------------------------------------------
/goh/simple.html:
--------------------------------------------------------------------------------
1 | <%: func SimpleQtc(u *model.User, buffer *bytes.Buffer) %>
2 |
3 | <%!
4 | import "github.com/SlinSo/goTemplateBenchmark/model"
5 | %>
6 |
7 |
8 |
9 | <%= u.FirstName %>
10 |
11 | Here's a list of your favorite colors:
12 |
13 | <% for _, colorName := range u.FavoriteColors { %>
14 | - <%= colorName %>
15 | <% } %>
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/goh/simple.html.go:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT!
2 | // Generate By Goh
3 |
4 | package template
5 |
6 | import (
7 | "bytes"
8 |
9 | "github.com/SlinSo/goTemplateBenchmark/model"
10 |
11 | Goh "github.com/OblivionOcean/Goh/utils"
12 | )
13 |
14 | func SimpleQtc(u *model.User, buffer *bytes.Buffer) {
15 | buffer.Grow(194)
16 | buffer.WriteString(`
17 |
18 |
19 |
20 |
21 |
22 | `)
23 | Goh.EscapeHTML(u.FirstName, buffer)
24 | buffer.WriteString(`
25 |
26 | Here's a list of your favorite colors:
27 |
28 | `)
29 | for _, colorName := range u.FavoriteColors {
30 | buffer.WriteString(`
31 | - `)
32 | Goh.EscapeHTML(colorName, buffer)
33 | buffer.WriteString(`
34 | `)
35 | }
36 | buffer.WriteString(`
37 |
38 |
39 |
40 | `)
41 | }
42 |
--------------------------------------------------------------------------------
/golang/footer.go:
--------------------------------------------------------------------------------
1 | package golang
2 |
3 | import (
4 | "github.com/valyala/bytebufferpool"
5 | )
6 |
7 | func WriteFooter(bb *bytebufferpool.ByteBuffer) {
8 | _, _ = bb.WriteString(``)
9 | }
10 |
--------------------------------------------------------------------------------
/golang/header.go:
--------------------------------------------------------------------------------
1 | package golang
2 |
3 | import (
4 | "html"
5 |
6 | "github.com/valyala/bytebufferpool"
7 | )
8 |
9 | func Header(bb *bytebufferpool.ByteBuffer, title *string) {
10 | _, _ = bb.WriteString(``)
11 | _, _ = bb.WriteString(html.EscapeString(*title))
12 | _, _ = bb.WriteString(`'s Home Page
13 |
14 | `)
15 | }
16 |
--------------------------------------------------------------------------------
/golang/index.go:
--------------------------------------------------------------------------------
1 | package golang
2 |
3 | import (
4 | "bytes"
5 | "html"
6 | "reflect"
7 | "strconv"
8 | "unsafe"
9 |
10 | "github.com/SlinSo/goTemplateBenchmark/model"
11 | "github.com/valyala/bytebufferpool"
12 | )
13 |
14 | var ()
15 |
16 | func UnsafeStrToBytes(s string) []byte {
17 | sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
18 | bh := reflect.SliceHeader{
19 | Data: sh.Data,
20 | Len: sh.Len,
21 | Cap: sh.Len,
22 | }
23 | return *(*[]byte)(unsafe.Pointer(&bh))
24 | }
25 |
26 | func Escape(bb *bytebufferpool.ByteBuffer, b []byte) {
27 | write := bb.Write
28 | j := 0
29 | for i, c := range b {
30 | switch c {
31 | case '<':
32 | _, _ = write(b[j:i])
33 | _, _ = write(strLT)
34 | j = i + 1
35 | case '>':
36 | _, _ = write(b[j:i])
37 | _, _ = write(strGT)
38 | j = i + 1
39 | case '"':
40 | _, _ = write(b[j:i])
41 | _, _ = write(strQuot)
42 | j = i + 1
43 | case '\'':
44 | _, _ = write(b[j:i])
45 | _, _ = write(strApos)
46 | j = i + 1
47 | case '&':
48 | _, _ = write(b[j:i])
49 | _, _ = write(strAmp)
50 | j = i + 1
51 | }
52 | }
53 | _, _ = write(b[j:])
54 | }
55 |
56 | var (
57 | strLT = []byte("<")
58 | strGT = []byte(">")
59 | strQuot = []byte(""")
60 | strApos = []byte("'")
61 | strAmp = []byte("&")
62 | )
63 |
64 | func hyper(bb *bytebufferpool.ByteBuffer, s string) {
65 | classFound := false
66 | idFound := false
67 | _ = bb.WriteByte('<')
68 |
69 | b := UnsafeStrToBytes(s)
70 |
71 | for _, c := range b {
72 | switch c {
73 | case '#':
74 | _, _ = bb.WriteString(" id=\"")
75 | idFound = true
76 | case '.':
77 | if idFound {
78 | _ = bb.WriteByte('"')
79 | }
80 | if !classFound {
81 | _, _ = bb.WriteString(" class=\"")
82 | classFound = true
83 | } else {
84 | _ = bb.WriteByte(' ')
85 | }
86 | default:
87 | _ = bb.WriteByte(c)
88 | }
89 | }
90 | if idFound || classFound {
91 | _ = bb.WriteByte('"')
92 | }
93 | _ = bb.WriteByte('>')
94 | }
95 |
96 | func Index3(bb *bytebufferpool.ByteBuffer, u *model.User, nav []*model.Navigation, title string) {
97 | _, _ = bb.WriteString(`
98 |
99 |
100 |
101 | Bob's Home Page
102 |
103 |
104 |
105 |
111 |
112 |
113 |
114 |
115 |
116 |
Hello Bob
117 |
118 |
Raw Content to be displayed
119 |
<div><div><div>Escaped</div></div></div>
120 |
Bob has 1 message
Bob has 2 messages
Bob has 3 messages
Bob has 4 messages
Bob has 5 messages
121 |
122 |
123 |
124 |
126 |
127 |
128 | `)
129 | }
130 |
131 | func Index2(bb *bytebufferpool.ByteBuffer, u *model.User, nav []*model.Navigation, title string) {
132 | _, _ = bb.WriteString(``)
133 | hyper(bb, "html")
134 | hyper(bb, "body")
135 | hyper(bb, "header")
136 | Header(bb, &title)
137 | hyper(bb, "/header")
138 | hyper(bb, "nav")
139 | Navigation(bb, nav)
140 | hyper(bb, "/nav")
141 | hyper(bb, "section")
142 | hyper(bb, "div.content")
143 | hyper(bb, "div.welcome")
144 | hyper(bb, "h4")
145 | _, _ = bb.WriteString(`Hello `)
146 | _, _ = bb.WriteString(html.EscapeString(u.FirstName))
147 | hyper(bb, "/h4")
148 | hyper(bb, "div.raw")
149 | _, _ = bb.WriteString(u.RawContent)
150 | hyper(bb, "/div")
151 | hyper(bb, "div.enc")
152 | Escape(bb, UnsafeStrToBytes(u.EscapedContent))
153 | hyper(bb, "/div>`)
162 | } else {
163 | _, _ = bb.WriteString(` messages`)
164 | }
165 |
166 | }
167 | hyper(bb, "/div>