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 [email protected].
For more options, visit https://groups.google.com/d/optout.