gotemplate
gotemplate copied to clipboard
Proposal: use type declarations for template declarations and instantiations
This proposal came about because of the following use case:
import _ "github.com/blah/model"
//go:generate gotemplate "github.com/ncw/gotemplate/set" mySet(*model.Person)
Notice the side effect import of "github.com/blah/model"
; model
is referenced in the template instantiation
In a local branch of github.com/ncw/gotemplate
I've modified the template instantiation code to also add imports referenced in the instantiation to the output file (looks through the *ast.ImportSpecs
in the *ast.File
that contains the instantiation).
This works, but it's a bit brittle because the instantiation is just a comment... for example in situations where one of the type parameters is a qualified identifier for a package that is not imported (because that package is not referenced anywhere else in the file).
Notice I'm totally ignoring .
imports... on the basis they are viewed as bad practice
So this got me thinking, could we instead switch to "special" type declarations as a means of declaring and instantiating templates?
package blah
// Template declarations take the form Template*. Exporting
// these types ensures they will be visible in godoc by default
// which is useful
//
// They must be a func type with no results
//
// The names of the parameters are irrelevant; only the types
// are used
//
type TemplateSet func(a A)
type A int
and then at an instance site:
package bing
import "github.com/mypkgs/blah"
//go:generate gotemplate
// Template instantiations take the form _Template*. The underscore
// ensures the type is _not_ exported (and also that it's sufficiently differentiated
// from other non-exported types in the package)
//
// The name that follows _Template* is irrelevant.. its type must be a func type
// according to the following rules:
//
// The template being instantiated is referenced as the type of the single result
// of the func type. The name of that result must be provided
// and that name will be used for the template instance
//
// The number of func parameters must match that of the template being instantiated
// and the types of the parameters are replaced position-wise
//
type _Template1 func(s string) (Blah blah.TemplateSet)
Thoughts?
Currently https://github.com/ncw/gotemplate/pull/29 is merged. It applies automatic import fixes like when you run goimports
. Also now (starting from Go 1.9) there is a possibility to use type aliases. I think it is a better solution for this particular case because a syntax is still concise and readable.