Simple and fast template engine for Go

Overview

fasttemplate

Simple and fast template engine for Go.

Fasttemplate performs only a single task - it substitutes template placeholders with user-defined values. At high speed :)

Take a look at quicktemplate if you need fast yet powerful html template engine.

Please note that fasttemplate doesn't do any escaping on template values unlike html/template do. So values must be properly escaped before passing them to fasttemplate.

Fasttemplate is faster than text/template, strings.Replace, strings.Replacer and fmt.Fprintf on placeholders' substitution.

Below are benchmark results comparing fasttemplate performance to text/template, strings.Replace, strings.Replacer and fmt.Fprintf:

$ go test -bench=. -benchmem
PASS
BenchmarkFmtFprintf-4                   	 2000000	       790 ns/op	       0 B/op	       0 allocs/op
BenchmarkStringsReplace-4               	  500000	      3474 ns/op	    2112 B/op	      14 allocs/op
BenchmarkStringsReplacer-4              	  500000	      2657 ns/op	    2256 B/op	      23 allocs/op
BenchmarkTextTemplate-4                 	  500000	      3333 ns/op	     336 B/op	      19 allocs/op
BenchmarkFastTemplateExecuteFunc-4      	 5000000	       349 ns/op	       0 B/op	       0 allocs/op
BenchmarkFastTemplateExecute-4          	 3000000	       383 ns/op	       0 B/op	       0 allocs/op
BenchmarkFastTemplateExecuteFuncString-4	 3000000	       549 ns/op	     144 B/op	       1 allocs/op
BenchmarkFastTemplateExecuteString-4    	 3000000	       572 ns/op	     144 B/op	       1 allocs/op
BenchmarkFastTemplateExecuteTagFunc-4   	 2000000	       743 ns/op	     144 B/op	       3 allocs/op

Docs

See http://godoc.org/github.com/valyala/fasttemplate .

Usage

	template := "http://{{host}}/?q={{query}}&foo={{bar}}{{bar}}"
	t := fasttemplate.New(template, "{{", "}}")
	s := t.ExecuteString(map[string]interface{}{
		"host":  "google.com",
		"query": url.QueryEscape("hello=world"),
		"bar":   "foobar",
	})
	fmt.Printf("%s", s)

	// Output:
	// http://google.com/?q=hello%3Dworld&foo=foobarfoobar

Advanced usage

	template := "Hello, [user]! You won [prize]!!! [foobar]"
	t, err := fasttemplate.NewTemplate(template, "[", "]")
	if err != nil {
		log.Fatalf("unexpected error when parsing template: %s", err)
	}
	s := t.ExecuteFuncString(func(w io.Writer, tag string) (int, error) {
		switch tag {
		case "user":
			return w.Write([]byte("John"))
		case "prize":
			return w.Write([]byte("$100500"))
		default:
			return w.Write([]byte(fmt.Sprintf("[unknown tag %q]", tag)))
		}
	})
	fmt.Printf("%s", s)

	// Output:
	// Hello, John! You won $100500!!! [unknown tag "foobar"]
Issues
  • Fails on GAE because of

    Fails on GAE because of "unsafe" import

    fasttemplate is used by echo, a web framework, for its logger. I currently use echo on Google App Engine, and it throws the following error :

    2017/01/16 16:08:42 go-app-builder: Failed parsing input: parser: bad import "unsafe" in github.com/valyala/fasttemplate/template.go from GOPATH
    

    As far as I understand, fasttemplate now relies heavily on unsafe for performance optimizations. How could we workaround this so that fasttemplate and echo stay compatible with GAE ?

    opened by etnbrd 6
  • remove vendor directory

    remove vendor directory

    • built on #14
    • modules supersede vendor directories: see wiki
      • this is not required, but does clean-up the repo, thus it is a separate pr
      • may be better to wait till 1.13 drops and the default is to ignore vendor
    opened by arnottcr 6
  • ExecFuncStringWithErr will not panick when f call returns error

    ExecFuncStringWithErr will not panick when f call returns error

    ExecFuncString will panic if f call returns an error. But panic isn't a good choice, why not just return that error to user? To avoid unexpected panic, user must recover before calling ExecFuncString, this is a hidden requirement to call ExecFuncString.

    For the sake of not breaking the compatibility, I added two new method called ExecFuncStringWithErr, which will not panic when f get an error, just returns an empty string and that error directly

    opened by caibirdme 5
  • Go 1.12

    Go 1.12

    He. Why do you have the minimum required version Go 1.12?

    opened by oherych 3
  • How to render HTML files

    How to render HTML files

    I only see the example of rendering html code, there is no example of rendering html files?

    question 
    opened by dxvgef 2
  • strings.Replacer drop in replacement

    strings.Replacer drop in replacement

    Hey @valyala! Thanks for the great lib! We have a lot of code, for url macros substitutioning with strings.Replacer. When we realised, that it was using too much memory, we chose your lib to optimize the performance.

    But the main problem is that we are using different replacers not once on a single template string, but many times. Example

    a := "{a}{b}"
    r := strings.Replace(a, "{a}", "1") // r == 1{b}
    ...(other part of code)...
    r = strings.Replace(r, "{b}", "2") // r == 12
    

    with replacers all is fine, but your engine skips the unknown values by default.

    a := "{a}{b}"
    r := fasttemplate.ExecuteString(a, "{", "}", map[string]intreface{}{"a": "1"}) // r == 1
    ...(other part of code)...
    r = fasttemplate.ExecuteString(r, "{", "}", map[string]intreface{}{"b": "2"}) // r == 1
    

    We made a wrapper for your lib, that fixes that. It actually just changes a little the stdTagFunc.

    What do you think of making this the default behaviour to make the engine more compatible with strings.Replacer? PR will be made on having your approve

    enhancement 
    opened by DoubleDi 2
  • Question: why a pool for each template?

    Question: why a pool for each template?

    Why do you use a worker pool for bytes.Buffers that are template-specific (vs. a global pool)? Is it for getting similar sized buffers each time, or is there another reason?

    question 
    opened by mathvav 1
  • GAE fix for unsafe

    GAE fix for unsafe

    Google app engine fix https://github.com/labstack/echo/issues/824

    Signed-off-by: Vishal Rana [email protected]

    opened by vishr 1
  • Gae fix

    Gae fix

    I just fixed the proposition of @vishr, so that it works on my env. A return statement was missing.

    opened by etnbrd 1
  • add mod file

    add mod file

    • go modules will be enabled in 1.13
    • go mod tidy was also run to include required dependencies
    • after merge it would be nice if you would tag this repo: e.g. v1.0.0
      • this will allow consumers something more consistent and readable than v0.0.0-20170224212429-dcecefd839c4
    opened by arnottcr 1
  • make ExecuteStringStd to be compatible to strings.Replacer on nested tags

    make ExecuteStringStd to be compatible to strings.Replacer on nested tags

    Hi @valyala! In #23 we added ExecuteStringStd which works as a drop-in replacement to strings.Replacer. It worked great, but we found a missmatch on nested start/end tags. Here is an example:

    {"x":"{id}"} 
    

    After replacing id with strings.Replacer:

    {"x":"1"} 
    

    After replacing id with fasttemplate.ExecuteStringStd:

    {"x":"{id}"}
    

    The reason is because fasttemplate takes the first start tag it finds, but strings.Replacer takes the closest to the end tag. So i made a PR to change the logic only in the ExecuteStringStd and other *Std funcs to make them compatible with strings.Replacer.

    Please review when you have the time

    opened by DoubleDi 0
  • Support escaping startTags (and endTags) in the template

    Support escaping startTags (and endTags) in the template

    Hey, thanks for this awesome library!

    At present, there is no way to include a startTag in the template string without the engine picking up on it as a tag:

    https://github.com/valyala/fasttemplate/blob/05015c3ec18b8e273134e723a9d4fedee5849cd1/template.go#L31

    I'd like to use this with some user defined templates, where there might well be a use case for them having whatever character I choose for the startTag in their template string proper. Using backslashes to escape would be the obvious option, but there's currently no functionality for anything of this sort in the library as far as I can see - so consider this a feature request :)

    Cheers!

    enhancement 
    opened by mashedkeyboard 0
  • Throwing error rather than panic in ExecuteFuncString

    Throwing error rather than panic in ExecuteFuncString

    I found that if ExecuteFunc returns an error, ExecuteFuncString will use panic. I think returning an error is more reasonable. See https://github.com/valyala/fasttemplate/blob/master/template.go#L91

    opened by lext-7 1
  • Add GetTags function.

    Add GetTags function.

    I'm storing templates in a database. When users of the admin UI go to create/update a template, I want to validate that it uses only fields that my code can actually provide. This PR adds a method for getting the names of all the tags used in a template, so I can do that validation.

    opened by btubbs 0
  • global lock contention when the generated Template object not reused by user

    global lock contention when the generated Template object not reused by user

    We are using this lib in our online system, and in a load test, we found that if the Template generated is not reused(eg.by sync.Map), there will be strong contention when the load is high:

    goroutine profile: total 18910
    18903 @ 0x102f20b 0x102f2b3 0x103fa4c 0x103f77d 0x10714df 0x1071d8f 0x1071d26 0x1071a5f 0x12feeb8 0x13005f0 0x13007c3 0x130107b 0x105c931
    #	0x103f77c	sync.runtime_SemacquireMutex+0x3c								/usr/local/go/src/runtime/sema.go:71
    #	0x10714de	sync.(*Mutex).Lock+0xfe										/usr/local/go/src/sync/mutex.go:134
    #	0x1071d8e	sync.(*Pool).pinSlow+0x3e									/usr/local/go/src/sync/pool.go:198
    #	0x1071d25	sync.(*Pool).pin+0x55										/usr/local/go/src/sync/pool.go:191
    #	0x1071a5e	sync.(*Pool).Get+0x2e										/usr/local/go/src/sync/pool.go:128
    #	0x12feeb7	github.com/valyala/fasttemplate/vendor/github.com/valyala/bytebufferpool.(*Pool).Get+0x37	/Users/xargin/go/src/github.com/valyala/fasttemplate/vendor/github.com/valyala/bytebufferpool/pool.go:49
    #	0x13005ef	github.com/valyala/fasttemplate.(*Template).ExecuteFuncString+0x3f				/Users/xargin/go/src/github.com/valyala/fasttemplate/template.go:278
    #	0x13007c2	github.com/valyala/fasttemplate.(*Template).ExecuteString+0x52					/Users/xargin/go/src/github.com/valyala/fasttemplate/template.go:299
    #	0x130107a	main.loop.func1+0x3a										/Users/xargin/test/go/http/httptest.go:22
    
    

    and after we use sync.Map to store the generated template objects, the piled goroutines disappear.

    Maybe you need to warn users about this?

    opened by cch123 0
  • How to pass int/bool/float to template

    How to pass int/bool/float to template

    template := "http://{{host}}/?q={{query}}&foo={{bar}}"
    	t := fasttemplate.New(template, "{{", "}}")
    	s1 := t.ExecuteString(map[string]interface{}{
    		"host":  "google.com",
    		"query": url.QueryEscape("hello=world"),
    		"bar":   22,
    })
    

    In my case, there are always int/bool/float type to template.

    Error:

    panic: tag="bar" contains unexpected value type=22. Expected []byte, string or TagFunc
    
    question 
    opened by sven0726 1
  • Another GAE problem

    Another GAE problem

    Trying to deploy my code based on Echo Framework, and getting GAE error:

    ERROR: (gcloud.app.deploy) Error Response: [9] Deployment contains files that cannot be compiled: Compile failed:
    /work_dir/github.com/valyala/fasttemplate/template.go:12: can't find import: "github.com/valyala/bytebufferpool"
    2017/12/22 23:38:09 go-app-builder: build timing: 15×compile (4.677s total), 0×link (0s total)
    2017/12/22 23:38:09 go-app-builder: failed running compile: exit status 2
    

    As far as I can see, GAE from Go 1.9.1 (I believe) stop reading subpackage vendors folder. When I delete /vendors folder in fasttemplate, build going through without issues.

    opened by stiks 4
  • Pass html with http.ResponseWriter

    Pass html with http.ResponseWriter

    Hi. I have implemented fasttemplate and have a question about pass ExecuteString value to http.ResponseWriter. How can it be done?

    opened by Arhius 0
  • adding Tags() method

    adding Tags() method

    opened by wzhliang 0
Owner
Aliaksandr Valialkin
Working on @VictoriaMetrics
Aliaksandr Valialkin
Goview is a lightweight, minimalist and idiomatic template library based on golang html/template for building Go web application.

goview Goview is a lightweight, minimalist and idiomatic template library based on golang html/template for building Go web application. Contents Inst

foolin 244 Aug 31, 2021
A general purpose golang CLI template for Github and Gitlab

golang-cli-template A general purpose project template for golang CLI applications This template serves as a starting point for golang commandline app

null 11 Aug 12, 2021
Handlebars for golang

raymond Handlebars for golang with the same features as handlebars.js 3.0. The full API documentation is available here: http://godoc.org/github.com/a

Aymerick 440 Aug 27, 2021
A handy, fast and powerful go template engine.

Hero Hero is a handy, fast and powerful go template engine, which pre-compiles the html templates to go code. It has been used in production environme

Lime 1.5k Sep 10, 2021
A demonstrative template for creating reliable Terraform modules

This repository provides a template for creating new Terraform modules. It's intended to demonstrate how one might go about standardizing their modules and subjecting them to integration tests in CI.

Patrick Delaney 3 Sep 1, 2021
Razor view engine for go

gorazor gorazor is the Go port of the razor view engine originated from asp.net in 2011. In summary, gorazor is: Extremely Fast. Templates are convert

null 787 Sep 13, 2021
HTML template engine for Go

Ace - HTML template engine for Go Overview Ace is an HTML template engine for Go. This is inspired by Slim and Jade. This is a refinement of Gold. Exa

Keiji Yoshida 803 Sep 10, 2021
Templating system for HTML and other text documents - go implementation

FAQ What is Kasia.go? Kasia.go is a Go implementation of the Kasia templating system. Kasia is primarily designed for HTML, but you can use it for any

Michał Derkacz 72 May 4, 2021
A template to build dynamic web apps quickly using Go, html/template and javascript

gomodest-template A modest template to build dynamic web apps in Go, HTML and sprinkles and spots of javascript. Why ? Build dynamic websites using th

Adnaan Badr 54 Aug 28, 2021
comparing the performance of different template engines

goTemplateBenchmark comparing the performance of different template engines full featured template engines Ace Amber Go Handlebars removed - Kasia Mus

null 189 Aug 31, 2021
The world’s most powerful template engine and Go embeddable interpreter.

The world’s most powerful template engine and Go embeddable interpreter

Open2b 17 Sep 15, 2021
Useful template functions for Go templates.

Sprig: Template functions for Go templates The Go language comes with a built-in template language, but not very many template functions. Sprig is a l

null 2.5k Sep 14, 2021
A sweet velvety templating package

Velvet Velvet is a templating package for Go. It bears a striking resemblance to "handlebars" based templates, there are a few small changes/tweaks, t

Buffalo - The Go Web Eco-System 71 Aug 15, 2021
pongo2 is a Django-syntax like templating-language

Django-syntax like template-engine for Go

Florian Schlachter 2k Sep 14, 2021
Simple and fast template engine for Go

fasttemplate Simple and fast template engine for Go. Fasttemplate performs only a single task - it substitutes template placeholders with user-defined

Aliaksandr Valialkin 530 Sep 10, 2021
⚗ The most advanced CLI template on earth! Featuring automatic releases, website generation and a custom CI-System out of the box.

cli-template ✨ ⚗ A template for beautiful, modern, cross-platform compatible CLI tools written with Go! Getting Started | Wiki This template features

null 10 Aug 28, 2021
Jet template engine

Jet Template Engine for Go Jet is a template engine developed to be easy to use, powerful, dynamic, yet secure and very fast. simple and familiar synt

null 829 Sep 7, 2021
"to be defined" - a really simple way to create text templates with placeholders

tbd "to be defined" A really simple way to create text templates with placeholders. This tool is deliberately simple and trivial, no advanced features

Luca Sepe 16 Aug 29, 2021
A complete Liquid template engine in Go

Liquid Template Parser liquid is a pure Go implementation of Shopify Liquid templates. It was developed for use in the Gojekyll port of the Jekyll sta

Oliver Steele 134 Sep 3, 2021