Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"range" action and "pipeline" clarification in text/html template package. Golang

I try to get some fine points in text/html template package. I've read its documentation from golang site. It's difficult to understand what exactly means the . (dot) in general and at a certain time in the range action. What exactly means "pipeline", maybe it's difficult to understand because my English is not mother tongue):

{{pipeline}}
The default textual representation of the value of the pipeline
is copied to the output.

Let's consider an example:

    data := map[string]interface{}{
        "struct": &Order{
            ID:     1,
            CustID: 2,
            Total:  3.65,
            Name: "Something",
        },
        "name1":  "Timur",
        "name2": "Renat",
    }
    t.ExecuteTemplate(rw, "index", data)

Here is "index":

{{define "index"}}
    {{range $x := .}}
        {{.}}
        <b>{{$x}}</b><br>
        <i>{{$.struct.ID}}</i><br>
        <br>
        # the lines below don't work and break the loop
        # {{.ID}}
        # or
        # {{.struct.ID}}

        # what if I want here another range loop that handles "struct" members
        # when I reach "struct" field in the data variable or just do nothing
        # and just continue the loop? 
    {{end}}
{{end}}

Output:

Timur
Timur
1

Renat
Renat
1

{1 2 3.65 Something}
{1 2 3.65 Something}
1

like image 753
Timur Fayzrakhmanov Avatar asked Jan 15 '15 21:01

Timur Fayzrakhmanov


1 Answers

Pipelines

A pipeline in the template package refers to the same sort of "piping" you would do at the command line.

For example, this is one way to get the default gateway assigned to your NIC on a Mac:

route -n get default | grep 'gateway' | awk '{print $2}'

Basically, the route -n get default is run first. Instead of printing the result to the console, the pipe character | says "take the output of the route command, and shove it into the grep command". At this point, grep 'gateway' runs on the input it receives from route. The output of grep is then shoved into awk. Finally, since there are no more pipes, the only output that you see on screen is whatever awk wants to print.

This is sort of the same in the template package. You can pipe values into method calls and chain them together. Such as:

{{ "Hello world!" | printf "%s" }}

Which is the equivalent of {{ printf "%s" "Hello World!" }}

See an example in the Go Playground here

Basically,

{{ "Hello World!" | printf "%s"           }}
    ^^^^^^^^^^^^               ^^^^^^^^^^
         |__________________________|

This is a very common thing in functional languages (from what I've seen.. I know its a thing in F#).

The dot .

The dot is "contextually aware". What this means, is that it changes meaning depending on where you put it. When you use it in the normal areas of your template, it is your model. When you use it in a range loop, it becomes the current value of the iteration.

See an example in the Go Playground here

In the linked example, only within the range loop, $x and . are the same. Once the loop ends, the dot refers back to the model passed into the template.

Checking for "struct"

Your struct is a key-value pair ... a map. To that end, you need to make sure you extract both parts in your range loop:

{{ range $key, $value = . }}

This will give you both the key and the value at each iteration. After that, you just need to check equality:

{{ if eq $key "struct" }}
    {{ /* $value.ID is the ID you want */ }}

See an example on the Go Playground here

Hopefully that helps.

like image 119
Simon Whitehead Avatar answered Nov 15 '22 07:11

Simon Whitehead