
Hero – A handy, fast and powerful Go template engine - lime66
https://github.com/shiyanhui/hero
======
ktzar
I've seen a few articles from Golang users saying that, after trying to fight
the standard library in many ways, they just end up using it since they
realise it's the best balance between usable and extensible. Taking how great
the Golang templating engine is, I'm not sure this is a step forward.

~~~
eknkc
I don't like Go Templates. My issue is that you can't have small calculations
easily. You'd have to add a lot of helper functions or prepare everything
before passing to template engine. Now there is too much coupling. And not
that fun. This one allowing inline Go code solves that issue.

Disclaimer: I wrote a template engine
([https://github.com/eknkc/amber](https://github.com/eknkc/amber)) to make
this easier (and I like that Jade syntax)

~~~
sepbot
I always considered the actual template to be the presentation layer relative
to the templating context. Having worked on large scale applications it has
become apparent to me that performing business logic in the presentation is
not the way to go. In my opinion, a templating application should be
architectured in such way that your data is transformed to exactly how you
want it to be presented prior to it getting to the presentation layer. Up in
presentation, you should really only have to worry about checking if a
condition is true or false or iterating a collection. From what I have seen of
Golang, some (not all) design decisions seem to have been made to make it
difficult to make such mistakes easily, so I would not be surprised if making
it difficult to do logic in the template was a conscious decision.

~~~
eknkc
While I agree in theory, I can't stand that in practice :).

For example, let's say I want to show a usage stat, I'd pass something like {
usage: 100, limit: 1000 } to the template engine. Let's say I want to add a
percentage. I believe the calculation should be on the presentation layer.
That's how I decide to present this particular data.

Go templates lack that functionality for no good reason. And if I'm gonna
calculate that on the backend, why exactly am I using a template engine? I'd
concatenate strings.

~~~
candiodari
Actually you can do function calls on Go templates [1], and indeed this is
what is done in practice. Libraries got written to do this, and badly
integrated [2].

You will quickly find if you use this that it's in fact worse: go templates
have LISP syntax. A set of atoms, specified in reverse Polish notation, doing
function application to all but the first atom.

[1]
[https://golang.org/pkg/text/template/#Template.Funcs](https://golang.org/pkg/text/template/#Template.Funcs)

[2]
[https://github.com/Masterminds/sprig](https://github.com/Masterminds/sprig)

~~~
eknkc
Yeah this is the reason I went ahead and wrote the template engine I mentioned
in the parent comment. It compiles down to go templates. I inject generic math
functions [1] and convert an expression like 4 + 5 * 3 to go template function
calls. It's ugly but the compiler generates it so whatever :)

[1]
[https://github.com/eknkc/amber/blob/master/runtime.go](https://github.com/eknkc/amber/blob/master/runtime.go)

------
davexunit
Another day, another string-based template engine that will lead to invalid
output and injection attacks. You don't need a new language specifically for
templates, you need to use a real programming language with real data
structures that represent the HTML/XML nodes.

[http://www.more-magic.net/posts/structurally-fixing-
injectio...](http://www.more-magic.net/posts/structurally-fixing-injection-
bugs.html)

------
asitdhal
Is template parsing a major bottleneck ?

What I know, most web apps need template parsing only at the beginning. Once
initial startup is done, delivery of content is mostly constant.

~~~
tiborsaas
It shouldn't be. I prefer template engines that I like the syntax and
documentation the most.

For low traffic efficacy doesn't matter, for high traffic you should always
cache the templates.

~~~
junke
Ideally, a template should be compiled into native code.

~~~
masklinn
Not necessarily.

1\. that requires parsing the template at compile-time (making it non-
overridable at runtime) or the ability to generate executable code at runtime
which break in NX-mandatory environment (e.g. appstore applications)

2\. the runtime version may be much faster than the compile-time one, e.g. the
rust Regex crate has both a runtime Regex structure and a regex! compiler
plugin, the latter is currently _significantly slower at runtime_ :
[https://github.com/rust-lang/regex#usage-regex-compiler-
plug...](https://github.com/rust-lang/regex#usage-regex-compiler-plugin)

~~~
junke
Yes, "compile/load/execute" can take longer than simply "eval". You have to
consider amortized costs: how often do you need to recompile your template (or
your regex)? Likewise, are you really going to override the template at
runtime or is the variable part of the template already compiled as branches
in the resulting code? Whatever needs to be dynamic _can_ be dynamic while
compiling as much as possible ahead of time.

------
fny
Pretty slick.

It's unfortunate the post title was "fastest go template engine" since that
draws away from how different the API is from the standard lib (think ERB/EJS
v Mustache).

While I'm personally in the "logicless" camp, I know a lot of people who'd
appreciate this. Even I would when building something quick and dirty.

------
fxbois
Emacs users, I've just added compatibility to web-mode.el (see [http://web-
mode.org](http://web-mode.org)) Screenshot:
[http://imgur.com/rlb2VWB](http://imgur.com/rlb2VWB)

~~~
wlkr
Thank you! Web-mode is a lovely package.

------
johnfn
I don't see a single positive comment on here.

Sorry, OP.

Nice work on your plugin and impressive benchmark statistics!

------
TeeWEE
Template parsing doesnt need to be super duper fast. Most of the time you can
cache the whole result.

I think its more important, to choose a good template language thats easy, and
doesnt mix code with template content.

~~~
lime66
Hero aims to be easy of use and fast.

------
mourner
Would love to see this adopted by Hugo. The default templating engine is ugly
as hell.

------
elithrar
Not escaping by default seems like a misfeature.

~~~
masklinn
According to the readme it seems to be escaping by default, kinda: <%= is
escaped and <%== is raw output.

So while the raw version is a bit too easy for my tastes (and the first to be
listed) the escaped version is still easier/shorter than raw.

------
fiatjaf
I'm for templating solutions that don't use a DSL or .html files, like this
one[1] I was developing but failed to put up in comparison with the others in
the goTemplateBenchmark repo.

[1]: [https://github.com/fiatjaf/hyperscript-
go](https://github.com/fiatjaf/hyperscript-go)

------
majewsky
The benchmarks in the README show a whole lot of templating engines, but
weirdly omit the standard library module:
[https://golang.org/pkg/text/template](https://golang.org/pkg/text/template)

That's more than enough to raise my eyebrow.

~~~
lime66
"Golang" is the standard library. And the code is here
[https://github.com/SlinSo/goTemplateBenchmark/tree/master/go](https://github.com/SlinSo/goTemplateBenchmark/tree/master/go).

~~~
majewsky
Huh, how could I miss this? (Maybe because the "G" looks too much like "C", so
I scanned "Co..." and skipped that entry.)

------
nkozyra
The benchmarks look good but if you're that abstracted from HTML I'd rather
just go all the way; something Jade-like takes this from being a half measure
to a full commitment.

------
superzadeh
Is that an ASP.NET / JSP ported in Go?

------
marcus_holmes
Adding a whole dependency to shave a few milliseconds off serve times (at
most) seems like a bad deal to me.

All the usual bad stuff that comes with dependencies: will it be maintained?
Will it have breaking changes? Will it leftpad?

And everyone knows the standard library template format, all the editors
support it, if another coder joins the team they'll know it.

Meh, maybe I'm just not the target market for this...

~~~
grey-area
These are not even milliseconds, the charts are in microseconds and a
reduction of 40 to < 10 µs... so basically just noise when compared with the
other things most apps will be doing, a 0.04 ms reduction.

I agree it's not worth the focus on fast, they should be focussed on improving
the API for the stdlib templates (for example loading templates is not
obvious, what I'd like to do is point it at a directory and load all templates
under that dir, being able to set layouts and partials would be nice etc).
Speed is not a big problem with the existing templating.

~~~
lime66
It's not noise. The benchmark's result is stable. Maybe the benchmark is too
simple. In production the templates are more complex than the benchmarks, so
the speed does count! But that doesn't mean that the easy-of-use is not
important. I want Hero to be fast, and easy of use too.

~~~
grey-area
It's very hard to benchmark things which are that fast, and very easy to make
mistakes (for example optimising away the thing you think you are measuring
because your benchmark does no real work with it and the compiler notices). So
on this homepage you have two benchmarks, which give these stats for stdlib:

Time: ~0.04ms

Memory usage: 2Kb

There is no context here and just a link to another benchmark which most
aren't going to bother to read. If your selling point is that you're the
fastest, you need to tell people why that's important, and what exactly is
faster. These graphs give zero details on the work done, and the
timings/memory usage suggest trivial work is done in the benchmark, which
means it's likely to be wrong. Is it measuring loading or evaluating or both
at once? How many templates, what is in them? Are they properly evaluated with
lots of keys in them? Do they test functions, methods, built-in functions?

If you're interested in speed, I'd suggest setting up your own real-world
benchmark, with separate charts for parse time (typically done once, of little
importance) and evaluation time for sets of templates which are 30-100
templates big and include lots of dynamic content and other templates. That's
close to real world use and will tell you if your library is a lot faster, it
might even give you far more impressive numbers (reduced render time of
typical templates from 100ms to 10ms for example).

Personally, like the parent, fastest is about 10th on my priorities list as
long as speed is adequate (and 0.04ms per template is adequate), below:
Correctness, Contextual escaping (very handy in stdlib, not supported?), Ease
of Use, Partials, Layouts, Syntax, Docs, Adding another dependency, etc.

As a third party dependency for a core feature which would require me to
impose your library on everyone who uses my library/app, your argument has to
be very strong and there have to be multiple reasons to adopt the library and
strong guarantees about future development/support. Speed is not enough, even
if it was an order of magnitude better on significantly slower results (say
100ms -> 10ms), it would be just one bullet point and far down the list.

I hope this is helpful.

------
strictfp
Jsp4go

------
myf01d
OMG I wish Python/Jinja2 had any performance near these numbers, I render some
complex pages at 15-25ms

------
warent
I acknowledge the capability of the engine which seems rather impressive. But
unfortunately it's basically obsolete.

How exactly are designers supposed to easily update? Why reinvent the wheel
when far more matured templating engines exist?

As the web moves to the front end, this seems like a step backwards

~~~
pjmlp
Depends on the point of view, I see as a step backwards to dump a pile of
JavaScript on the browser.

Many web sites are perfectly fine with pure HTML/CSS.

