• Stars
    star
    258
  • Rank 158,189 (Top 4 %)
  • Language
    Go
  • License
    MIT License
  • Created about 10 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Package based templating system for Go

Go templates

Note: with the advent of generics in go 1.18 this package is now obsolete. Please use go 1.18 and its generic facilities instead. I will keep this package here for existing users, but I won't be updating it any more - @ncw


This tool manages package based templates for the Go language using "go generate" which requires go 1.4.

Build Status

Install

Install using go get

go get github.com/ncw/gotemplate/...

and this will build the gotemplate binary in $GOPATH/bin.

It will also pull in a set of templates you can start using straight away

Using templates

To use a template, first you must tell gotemplate that you want to use it using a special comment in your code. For example

//go:generate gotemplate "github.com/ncw/gotemplate/set" mySet(string)

This tells go generate to run gotemplate and that you want to use the set template with the string type parameter and with the local name mySet.

Now run go generate in your code directory with no arguments. This will instantiate the template into a file called gotemplate_mySet.go which will provide a mySet type and newMySet and newSizedMySet functions to make them. Note that the first letter of your custom name is still capitalized when it is not at the beginning of the new name.

$ go generate
substituting "github.com/ncw/gotemplate/set" with mySet(string) into package main
Written 'gotemplate_mySet.go'

If you wish to change what the output file names look like then you can use the -outfmt format flag. The format must contain a single instance of the %v verb which will be replaced with the template instance name (default "gotemplate_%v")

Instantiating the templates into your project gives them the ability to use internal types from your project.

If you use an initial capital when you name your template instantiation then any external functions will be public. Eg

//go:generate gotemplate "github.com/ncw/gotemplate/set" MySet(string)

Would give you MySet, NewMySet and NewSizedMySet instead.

You can use multiple templates and you can use the same template with different parameters. In that case you must give it a different name, eg

//go:generate gotemplate "github.com/ncw/gotemplate/set" StringSet(string)
//go:generate gotemplate "github.com/ncw/gotemplate/set" FloatSet(float64)

If the parameters have spaces in then they need to be in quotes, eg

//go:generate gotemplate "github.com/ncw/gotemplate/sort" "SortGt(string, func(a, b string) bool { return a > b })"

Renaming rules

All top level identifiers will be substituted when the template is instantiated. This is to ensure that they are unique if the template is instantiated more than once.

Any identifiers with the template name in (eg Set) will have the template name (eg Set) part substituted. If the template name does not begin the identifier, Go's casing style is respected and the first letter of your new identifier is capitalized. (eg 'newMySet' instead of 'newmySet').

Any identifiers without the template name in will just be post-fixed with the template name.

So if this was run

//go:generate gotemplate "github.com/ncw/gotemplate/set" MySet(string)

This would substitute these top level identifiers

  • Set to MySet
  • NewSet to NewMySet
  • NewSizedSet to NewSizedMySet
  • utilityFunc to utilityFuncMySet

Depending on whether the template name is public (initial capital) or not, all the public external identifiers will have their initial capitals turned into lower case. So if this was run

//go:generate gotemplate "github.com/ncw/gotemplate/set" mySet(string)

This would substitute

  • Set to mySet
  • NewSet to newMySet
  • NewSizedSet to newSizedMySet
  • utilityFunc to utilityFuncMySet

Installing templates

Templates can be installed using go get because they are normal Go packages. Eg

go get github.com/someones/template

Will install a template package you can use in your code with

//go:generate gotemplate "github.com/someones/template" T(Potato)

Then instantiate with

go generate

Source control for templates

It is expected that the generated files will be checked into version control, and users of your code will just run go get to fetch it. go generate will only be run by developers of the package.

Writing templates

Templates are valid go packages. They should compile and have tests and be usable as-is. Because they are packages, if you aren't writing a public template you should put them in a subdirectory of your project most likely.

To make a Go package a template it should have one or more declarations and a special comment signaling to gotemplate what the template is called and what its parameters are. Supported parameterized declarations are type, const, var and func.

Here is an example from the set package.

// template type Set(A)
type A int

This indicates that the base name for the template is Set and it has one type parameter A. When you are writing the template package make sure you use A instead of int where you want it to be substituted with a new type when the template is instantiated.

Similarly, you could write a package with a const parameter.

// template type Vector(A, N)
type A int
const N = 2

type Vector[N]A

This indicates that the base name for the template is Vector and it has one type parameter A and one constant parameter N. Again, all uses of N in the template code will be replaced by a literal value when the template is instantiated.

All the definitions of the template parameters will be removed from the instantiated template.

All test files are ignored.

Bugs

There may be constraints on the types which aren't understood by gotemplate. For instance the set requires that the types are comparable. If you try this you'll get a compile error for example.

//go:generate gotemplate "github.com/ncw/gotemplate/set" BytesSet([]byte)

Only one .go file is used when reading template definitions at the moment (programmer laziness - will fix at some point!)

Changelog

  • v0.06 - 2017-05-05
    • Add -outfmt string (thanks Paul Jolly)
  • v0.05 - 2016-02-26
    • Fix docs and examples
    • More set methods - thanks Adam Willis
    • Fix missing error check in code generation
  • v0.04 - 2014-12-23
    • Fixed multi-line type declarations
  • v0.03 - 2014-12-22
    • Allow const and var to be substituted as template parameters
  • v0.02 - 2014-12-15
    • Fixed multi-line const/var declarations
  • v0.01 - 2014-12-10
    • Change renaming rules to make better Go names. This only affects private exports, eg for mySet in the example above,
      • NewSet becomes newMySet (was newmySet)
      • NewSizedSet becomes newSizedMySet (was newSizedmySet)
      • utilityFunc becomes utilityFuncMySet (utilityFuncmySet)
    • This is a backwards incompatible change
  • v0.00 - 2014-10-05
    • First public release

Ideas for the future

Make a set type for non comparable things? Pass in a compare routine?

Make sure that types implement an interface?

Optional parameters?

Philosophy

All code (templates, use of templates and template instantiations) should be normal Go code - no special types / extensions.

All configuration done with specially formatted comments

Should provide lots practical templates people can use right now.

License

This is free software under the terms of MIT the license (check the COPYING file included in this package).

Portions of the code have been copied from the Go source. These are identified by comments at the head of each file and these are Copyright (c) The Go Authors. See the GO-LICENSE file for full details.

Contact and support

The project website is at:

There you can file bug reports, ask for help or contribute patches.

Authors

Contributors

More Repositories

1

stressdisk

Stress test your disks / memory cards / USB sticks before trusting your valuable data to them
Go
320
star
2

swift

Go language interface to Swift / Openstack Object Storage / Rackspace cloud files (golang)
Go
313
star
3

directio

This is library for the Go language to enable use of Direct IO under all OSes
Go
298
star
4

gmp

Go language interface to GMP - GNU Multiprecision Library (golang)
Go
108
star
5

go-nflog-acctd

IP accounting using NFLOG under Linux iptables
Go
53
star
6

oauthproxy

This is an oauth2 proxy server
Go
34
star
7

johnroids

Johnroids is an old style asteroids game implemented in go, gopherjs and go/wasm
Go
29
star
8

dropbox

Go (golang) client library for the Dropbox core and Datastore API with support for uploading and downloading encrypted files.
Go
11
star
9

go-deadlocks-talk

Sample code for my Go Deadlocks talk
Go
9
star
10

make_test_files

A program to generate test files
Go
8
star
11

fsyncbench

Benchmark fsync
Go
8
star
12

fetch-actions-logs

Fetch your GitHub Actions logs
Go
8
star
13

iprime

All integer Mersenne prime checker
C++
7
star
14

oxo3d

Oxo3d - 3D noughts and crosses / tic tac toe
Go
6
star
15

ioccc2012

Mersenne prime prover for IOCCC 2012
C
6
star
16

mirror

Neopixel based Infinity Mirror running on Raspbery Pi Pico-W with Micropython
Python
5
star
17

snake-puzzle

A solver for the Snake Puzzle using python with a Jupyter notebook
Jupyter Notebook
5
star
18

rcloneguiexperiment

Rclone GUI experiment
JavaScript
5
star
19

pwhash

Mirror of antihe.ro/pwhash
Go
5
star
20

pslq

Go (golang) library and cli tool for using the PSLQ integer relation algorithm.
Go
3
star
21

mandelterm

View Mandelbrot sets in your terminal
Go
3
star
22

www

Nick Craig-Wood's Website
Python
2
star
23

router-rebooter

Reboots your Netgear DG834 ADSL router when the internet connection drops
Python
2
star
24

parse-actions-logs

Parse GitHub actions logs for go test results
Go
2
star
25

.github

Default community health files for ncw
1
star
26

rclone-archive

Archive of old rclone branches
Go
1
star
27

euler_bbp

Programs and paper to demonstrate Euler's BBP-type formulae for pi
TeX
1
star