Customized Go template FuncMap example

843 views
Skip to first unread message

Tong Sun

unread,
Jul 6, 2017, 11:01:01 PM7/6/17
to golang-nuts
I'm trying my best to make the following Go template FuncMap example works:

https://play.golang.org/p/1-JYseLBUF

If I comment out line 55, 56 and un-comment line 54, it works just fine. 

What I was trying to do is to un-comment line 31, and use DefaultFuncs() or something alike to replace line 54. I.e., I'm trying to wrap the myFuncMap into a callable function. 

How can I do that? Thx

Matt Harden

unread,
Jul 9, 2017, 10:20:44 PM7/9/17
to Tong Sun, golang-nuts
Why are you trying to do that? It feels like you're trying to do object-oriented programming in Go. Don't do that. What are you trying to achieve that the *template.Template type doesn't allow?

If you just want a template with a FuncMap already applied, write a function to do that:

func MyTemplate(name string) *template.Template {
    return template.New(name).Funcs(map[string]interface{}{"title": strings.Title})
}


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tong Sun

unread,
Jul 9, 2017, 11:15:55 PM7/9/17
to Matt Harden, golang-nuts
Thanks Matt. 

What I'm trying to do is to modulelize customized Go template functions, say one module provide advanced regexp support, while another one specialized in text formatting (vertical aligning, text folding in column, etc), so on and so forth, each of the module has a collection of their own customized template functions

The goal is to define such modules separately, as a building block, provide them as libraries, and the end user can pick and choose what what, and chain the customized template functions together using a series of `.Funcs` calls. 

That's what I had in mind. Hope that I've express it clear enough. Thx. 

Matt Harden

unread,
Jul 13, 2017, 10:11:14 PM7/13/17
to Tong Sun, golang-nuts
Can you do what you want just by building a number of template.FuncMap values, and then to use them the user just calls t.Funcs(module1.FuncMap).Funcs(module2.FuncMap), adding the function maps they want that way?

I don't think you need your own custom version of the Template type.

Tong Sun

unread,
Jul 14, 2017, 10:30:55 AM7/14/17
to Matt Harden, golang-nuts
On Thu, Jul 13, 2017 at 10:10 PM, Matt Harden  wrote:
Can you do what you want just by building a number of template.FuncMap values, and then to use them the user just calls t.Funcs(module1.FuncMap).Funcs(module2.FuncMap), adding the function maps they want that way?

 Yeah, sure, but for writing a library, it'll not be that quite easy, because,

I don't think you need your own custom version of the Template type.

Yes I do, please take a look at 

I.e., I want the library works for both text and html templates, building a number of template.FuncMap values would be troublesome in this case, because in my mind the template.FuncMap can be either a text or html template, but not both. 

Matt Harden

unread,
Jul 14, 2017, 9:28:35 PM7/14/17
to Tong Sun, golang-nuts
If the type of the map is map[string]interface{}, it can be used with either type of template. https://play.golang.org/p/-sFMhKOtNN

If you create your own template type, then you can also create your own FuncMap type, and in your own Funcs method, pass it on to the underlying template:

type FuncMap map[string]interface{}

type Template struct{
    tmpl interface{}
}

func (t *Template) Funcs(fm FuncMap) *Template {
    fmBase := map[string]interface{}(fm)
    switch tt := t.tmpl.(type) {
    case *htmltemplate.Template:
        return Template{tmpl: tt.Funcs(fmBase)}
    case *texttemplate.Template:
        return Template{tmpl: tt.Funcs(fmBase)}
    default:
        // this shouldn't happen
        panic("unrecognized template type")
}


But you also then have no choice but to wrap every single method that (that you want to also have) returns a *Template, so that it returns your own template type instead. That's why I don't think it's a good idea to create your own Template type.

Tong Sun

unread,
Jul 14, 2017, 9:32:42 PM7/14/17
to Matt Harden, golang-nuts
Gotya. Thanks for all the helps!

Matt Ho

unread,
Jul 15, 2017, 12:51:11 PM7/15/17
to golang-nuts, matt....@gmail.com
Given that text and html templates are separate calls anyways, why not just make separate calls for your custom funcmap?  For example:

package template

import (
  html "html/template"
  text "text/template"
)

func Html(name string, fm html.FuncMap) *html.Template {
  return html.New(name).Funcs(fm)
}

func Text(name string, fm text.FuncMap) *text.Template {
  return text.New(name).Funcs(fm)
}

Tong Sun

unread,
Jul 15, 2017, 2:43:54 PM7/15/17
to Matt Ho, golang-nuts
Thanks. 

I don't know what kind of goals you are trying to achieve, but here are mine:

What I'm trying to do is to modulelize customized Go template functions, say one module provide advanced regexp support, while another one specialized in text formatting (vertical aligning, text folding in column, etc), so on and so forth, each of the module has a collection of their own customized template functions

The goal is to define such modules separately, as a building block, provide them as libraries, and the end user can pick and choose what what, and chain the customized template functions together using a series of `.Funcs` calls. 

Thus, I was trying to wrap the myFuncMap into a callable function, so that the library works for both text and html templates. 

So how is the following fitting into the above goals? Thx. 
Reply all
Reply to author
Forward
0 new messages