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 golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to