Giter Club home page Giter Club logo

fasttemplate's Introduction

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"]

fasttemplate's People

Contributors

ahrtr avatar caibirdme avatar doubledi avatar jlauinger avatar urandom2 avatar valyala avatar vishr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fasttemplate's Issues

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

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

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.

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:

n := bytes.Index(s, a)

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!

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 ?

Go 1.12

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

is map[string]string more effecient than map[string]interface{} ?

In my application. all my template subsitutions are strings. I want to improve the templating engine more, such that it won't assert the interface or somehow, and directly stream the string as is.

since all my database read values are in strings. I want to use map[string]string insead if it would increase the subsitution effieciency more.

How is this approach possible ?

thank you in advance

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?

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.

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.