The best idea I can think of (without digging and modifying text/template) is to use special tokens and replace them afterwards... Of course this approach has limitations in what it can do.
*// note: code untested and incomplete* type Token string type Queries struct { pending sync.WaitGroup mu sync.Mutex responses map[Token]string } func (q *Queries) createToken() Token { return unique token } func (q *Queries) Do(fn func() string) Token { token := q.createToken() q.pending.Add(1) go func(){ defer q.pending.Done() result := fn() q.mu.Lock() q.responses[token] = result q.mu.Unlock() }() return token } func (q *Queries) Wait(){ q.pending.Wait() } func (q *Queries) Patch(data []byte) []byte { // replace tokens with responess } func main() { q := NewQueries() var funcMap = template.FuncMap { "sleep": func() Token { return q.Do(func() string { time.Sleep(1 * time.Second); return "slept" }) }, } tmpl, _ := template.New("test").Funcs(funcMap).Parse("{{sleep}} {{sleep}} {{sleep}}") var buf bytes.Buffer tmpl.Execute(&buf, nil) q.Wait() os.Stdout.Write(q.Patch(buf.Bytes)) } The other approach would be to do multiple passes: 1. execute template 2. collect funcs that haven't been run yet 2.1. no funcs left --> output 3. execute these funcs, cache the func values 4. goto step 1 using the cache On Wednesday, 31 May 2017 16:26:15 UTC+3, Michael Brown wrote: > > I am designing a system that will heavily use text/template processing and > I've run into one issue that is going to be a show stopper for me if I > can't figure out a way around it. > > Execute() on a template will run all of the functions in the template > serially. > > For example, when you run the code below, you can see it output "slept" > once every second until it completes after 3 seconds. In this example, the > sleep is simulating an RPC call to another process that may take some > considerable time (few tenths of a second), but there will be a large > number of these calls that could all theoretically run in parallel (ie. > there are no data dependencies between them). I'd really like to know a way > that I could have the templating engine run all of the functions at once > and collect the output, ie. in the example below, the entire program should > run in 1 second. > > package main > > > import ( > > "text/template" > > "os" > > "time" > > ) > > > var funcMap = template.FuncMap { > > "sleep": func() string { time.Sleep(1 * time.Second); return "slept" }, > > } > > > func main() { > > tmpl, _ := template.New("test").Funcs(funcMap).Parse("{{sleep}} > {{sleep}} {{sleep}}") > > tmpl.Execute(os.Stdout, nil) > > } > > > -- 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+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.