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 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"]
Owner
Aliaksandr Valialkin
Working on @VictoriaMetrics
Aliaksandr Valialkin
Comments
  • 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
  • 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 ?

  • 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

  • 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

  • Fix possible memory confusion in unsafe slice cast

    Fix possible memory confusion in unsafe slice cast

    I found an incorrect cast from string to []byte in unsafe.go. The problem is that when reflect.SliceHeader is created as a composite literal (instead of deriving it from an actual slice by cast), then the Go garbage collector will not treat its Data field as a reference. If the GC runs just between creating the SliceHeader and casting it into the final, real []byte slice, then the underlying data might have been collected already, effectively making the returned []byte slice a dangling pointer.

    This has a low probability to occur, but projects that import this library might still use it in a code path that gets executed a lot, thus increasing the probability to happen. Depending on the memory layout at the time of the GC run, this could potentially create an information leak vulnerability.

    This PR changes the function to create the reflect.SliceHeader from an actual slice by first instantiating the return value.

  • 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
  • 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?

  • Nested object in map[string]interface{}.

    Nested object in map[string]interface{}.

    Is it possible to match a nested map object's key? For example I having a variable shown below:

    input := map[string]interface{}{
      "user": map[string]interface{}{
    	  "name": "James",
    	  "age":  "20",
      },
    }
    

    Example template

    "Hi, my name is {{user.name}}, I'm {{user.age}} years old."
    

    How do I get the {{user.name}} as the tags for template when calling ExecuteStringStd() ? I tried with {{user.name}} but it doesn't work.

  • 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

  • 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!

  • 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

  • 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.

  • 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?

A handy, fast and powerful go template engine.
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

Dec 27, 2022
Simple system for writing HTML/XML as Go code. Better-performing replacement for html/template and text/template

Simple system for writing HTML as Go code. Use normal Go conditionals, loops and functions. Benefit from typing and code analysis. Better performance than templating. Tiny and dependency-free.

Dec 5, 2022
Api-go-template - A simple Go API template that uses a controller-service based model to build its routes

api-go-template This is a simple Go API template that uses a controller-service

Feb 18, 2022
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

Dec 25, 2022
A template to build dynamic web apps quickly using Go, html/template and javascript
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

Dec 29, 2022
Wrapper package for Go's template/html to allow for easy file-based template inheritance.

Extemplate Extemplate is a small wrapper package around html/template to allow for easy file-based template inheritance. File: templates/parent.tmpl <

Dec 6, 2022
Made from template temporalio/money-transfer-project-template-go
Made from template temporalio/money-transfer-project-template-go

Temporal Go Project Template This is a simple project for demonstrating Temporal with the Go SDK. The full 20 minute guide is here: https://docs.tempo

Jan 6, 2022
Go-project-template - Template for a golang project

This is a template repository for golang project Usage Go to github: https://git

Oct 25, 2022
Go-api-template - A rough template to give you a starting point for your API

Golang API Template This is only a rough template to give you a starting point f

Jan 14, 2022
The world’s most powerful template engine and Go embeddable interpreter.
The world’s most powerful template engine and Go embeddable interpreter.

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

Dec 23, 2022
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

Jan 4, 2023
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

Jan 4, 2023
A complete Liquid template engine in Go
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

Dec 15, 2022
gtpl is a template engine for glang

gtpl 使用必读 gtpl is a HTML template engine for golang gtpl 是一个 go 语言模板引擎,它能以极快的速度进行模板语法分析。相比 go 语言官方库 html/template,gtpl 的语法有着简练、灵活、易用的特点。

Nov 28, 2022
This my project template for making fiber with SSR taste by empowered mustache engine.

SSR-FIBER-TEMPLATE This my project template for making fiber with SSR taste by empowered mustache engine. Folder Hierarchy Name Description configs Co

May 9, 2022
A sane and simple Go REST API template.

Gosane ??‍♀️ A sane and simple Go REST API template. Clone me and edit me to fit your usecase. What is Gosane? Gosane is a cloneable API template to g

Dec 7, 2022
Code your next Go web project with (a) Mojito! No matter if its an API or a website, go-mojito assists you with dependency injection, simple routing, custom request / response objects and template rendering
 Code your next Go web project with (a) Mojito! No matter if its an API or a website, go-mojito assists you with dependency injection, simple routing, custom request / response objects and template rendering

Go-Mojito is a super-modular library to bootstrap your next Go web project. It can be used for strict API-only purposes as well as server-side renderi

May 1, 2022
Simple template suitable for building a webapp backend MVP written in go

A Simple Go Project Template - Suited for Webapp MVPs A simple go project structure setup with all dependencies you need to get your MVP off the groun

Oct 23, 2022
A simple template using Fiber for me to bootstrap API services quickly.

Fiber Template A simple template using Fiber for me to bootstrap API services quickly. Features Fiber GORM air for hot reloading ... and possibly more

Dec 16, 2021