Great! If I had checked this thread when you posted this I (probably) could
have saved myself 3 hours of work.
I got it working with a two-pass scheme using text/template and some
channels.
Here is what I came up with:
package main
import (
"text/template"
"bytes"
"context"
"fmt"
"github.com/google/uuid"
"time"
)
type resultpair struct {
key string
value string
}
func getFuncMap(ctx context.Context, resultsQueue chan resultpair) (*int,
template.FuncMap) {
totalJobs := 0
var funcMap = template.FuncMap{
"sleep": func() string {
totalJobs = totalJobs + 1
token := uuid.New()
go func() {
time.Sleep(1 * time.Second)
resultsQueue <- resultpair{token.String(), "REAL_VALUE!"}
}()
return "{{ getOutput \"" + token.String() + "\" }}"
},
}
return &totalJobs, funcMap
}
func getFuncMapNested(ctx context.Context, output map[string]string)
template.FuncMap {
var funcMapNested = template.FuncMap{
"getOutput": func(input string) string { return output[input] },
}
return funcMapNested
}
func main() {
initial := "{{sleep}} {{sleep}} {{sleep}}"
resultsQueue := make(chan resultpair)
outputQueue := make(chan map[string]string)
// totalJobs is decieving: only ever accessed by one thread at a time,
so shouldn't need locking (I think)
totalJobs, funcMap := getFuncMap(context.TODO(), resultsQueue)
fmt.Printf("About to execute first template: %s\n", initial)
fmt.Printf("TOTAL JOBS: %d\n", *totalJobs)
tmpl, _ := template.New("test").Funcs(funcMap).Parse(initial)
var buf bytes.Buffer
tmpl.Execute(&buf, nil)
fmt.Printf("Got translated template: %s\n", buf.String())
fmt.Printf("TOTAL JOBS: %d\n", *totalJobs)
go func(totalJobs *int) {
var results map[string]string
results = make(map[string]string)
for i := 0; i < *totalJobs; i++ {
res := <-resultsQueue
results[res.key] = res.value
}
outputQueue <- results
close(outputQueue)
}(totalJobs)
output := <-outputQueue
close(resultsQueue)
fmt.Printf("Output of the goroutine: %s\n", output)
funcMapNested := getFuncMapNested(context.TODO(), output)
tmpl2, _ :=
template.New("nested").Funcs(funcMapNested).Parse(buf.String())
var buf2 bytes.Buffer
tmpl2.Execute(&buf2, nil)
fmt.Printf("results: %s\n", buf2.String())
}
OUTPUT:
$ time go run ./commands/try.go
About to execute first template: {{sleep}} {{sleep}} {{sleep}}
TOTAL JOBS: 0
Got translated template: {{ getOutput
"bc7dcfa0-89d9-45e9-bd40-eb2db6f51db0" }} {{ getOutput
"f2539f15-378b-408d-8c6e-d3822e985a6b" }} {{ getOutput
"56c9d239-d08d-43e8-80de-dd97ef157b6a" }}
TOTAL JOBS: 3
Output of the goroutine:
map[bc7dcfa0-89d9-45e9-bd40-eb2db6f51db0:REAL_VALUE!
f2539f15-378b-408d-8c6e-d3822e985a6b:REAL_VALUE!
56c9d239-d08d-43e8-80de-dd97ef157b6a:REAL_VALUE!]
results: REAL_VALUE! REAL_VALUE! REAL_VALUE!
real 0m1.319s
user 0m0.278s
sys 0m0.098s
On Wednesday, May 31, 2017 at 9:09:51 PM UTC-5, robfig wrote:
>
> We do this exact thing except using closure templates
> https://blog.gopheracademy.com/advent-2014/soy-programmable-templates/
>
--
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.