How to set a golang variable to a template variable - go

I am new to golang and want to understand how to assign a template variable in golang using the golang variable.
I am using go-swagger to generate go code.
Below is the piece of a customized template to generate my swagger client.
func demo() {
{{range .Operations}}
Value := main.CheckAvail(*{{.Package}}.{{ pascalize .Name }})
{{$value := .Value}}
{{if $value }}
{{ pascalize .Name }}
{{end}}
{{end}}
}
But it gives me the error that:
" <.Value>: can't evaluate field Value in type generator.GenOperation ".
How do I assign the value to the $value? Any help?

This is not possible. The template file is a wire frame for a go file. It just generates a file of go code, which is not executed yet.
All in {{ ... }} is evaluated, when the template is parsed. At this point, all text outside the curly braces is just plain text. After the (successful) execution of the template generation the generated text will be picked up by the go compiler and compiled (if it is correct go code).
In this case you cannot evaluate Value.

Related

How do you parse brackets from path string on a variable return in Hugo?

I am writing a layout template for a Hugo generated post/page. The .yaml header is
image:
- post/mytitle/image.jpg
The template incorporates the variable in Hugo as
{{ .Params.Image }}
When served, the variable is returned as
[post/mytitle/image.jpg]
My html then becomes
<img src="[post/mytitle/image.jpg]"/>
which is 404 in the browser. I've tried a number of Hugo functions to no avail like {{ trim .Param.Image "[]" }} and {{ subset .Params.Image 1 -1 }} and {{ print .Params.Image }}. Each time Hugo returned the error: "error calling substr: unable to cast []string{"post/mytitle/image.jpg"} of type []string to string".
How do I get the variable to return the string without the brackets, or alternatively, how do I omit the brackets from the string?
In Go template, you access an item in a slice with index:
{{ index .Params.Image 0 }}
The question is why the value is a sequence in the first place. You could simply do
image:
post/mytitle/image.jpg
Then you could keep the original syntax since it is now a simple value, not a sequence.
If you want to possibly include multiple images, you'd do
{{ range .Params.Image }}<img src="{{.}}">{{ end }}
Then you can have
image:
- post/mytitle/image.jpg
- post/mytitle/anotherimage.jpg

How to declare a global variable in a template?

I need to write a template where I first define some variables, and then use them in what will be generated from the template:
{{ if $value.Env.CADDY_URL }}
{{ $url := $value.Env.CADDY_URL }}
{{ else }}
{{ $url := printf "http://%s.example.info" $value.Name }}
{{ end }}
{{/* more template */}}
{{/* and here I would like to use $url defined above */}}
{{ $url }}
I get the error
undefined variable "$url"
Reading the documentation, I see that
A variable's scope extends to the "end" action of the control structure ("if", "with", or "range") in which it is declared, or to the end of the template if there is no such control structure.
Does this mean that there are no global (or scoped on the whole template) variables? Or is there a way to define $url so that it can be reused later in the template?
Variables are scoped. You create the $url variable inside the {{if}} and {{else}} blocks, so they are not visible outside of those blocks.
Create the variable before the {{if}}, and use assignment = instead of declaration :=:
{{$url := ""}}
{{ if . }}
{{ $url = "http://true.com" }}
{{ else }}
{{ $url = "http://false.com" }}
{{ end }}
{{ $url }}
Testing it:
t := template.Must(template.New("").Parse(src))
fmt.Println(t.Execute(os.Stdout, true))
fmt.Println(t.Execute(os.Stdout, false))
Output (try it on the Go Playground):
http://true.com<nil>
http://false.com<nil>
Note: Modifying template variables with assignment was added in Go 1.11, so you need to build your app with Go 1.11 or newer. If you're using an older version, you cannot modify values of template variables.
Edit: I've found a duplicate: How do I assign variables within a conditional
You can mimic "changeable template variables" in earlier versions, see this question for examples: In a Go template range loop, are variables declared outside the loop reset on each iteration?

Golang: Ordering map by slice in Go templates

I have a question about how to order a map by a slice in Go Templates and if it is possible.
Problem: I have a slice of ordered variable names that I want to display on a website, accompanying them I have a map of metadata of variable information that I would like to display together with the variable.
If I have the following struct that I pass in to the template:
type Data struct {
Variables []string
Information map[string]int
}
I would iterate over the slice and pass the variable name in to the map
{{ range $v := .Variables }} {{ index .Information $v }} {{ end }} // Doesn't work.
Here's a Go Playground with the example.
https://play.golang.org/p/AL2csnXdoU
Question: How can I do this?
I am fairly new to Golang. Thankful for any input.
The following should work. To access .Information inside range, you should use $, which is basically d in your Playground example.
{{ range .Variables }} {{ index $.Information . }} {{ end }}

Golang/Revel template engine template with variable

Is there a way to pass a variable that was iterated over into a Golang/Revel template?
For example, in "header.html", I have
{{range .templates}}
{{template "something" .}}
{{end}}
How can I use current index from the array as an argument to template? I tried embedding another {{.}} as shown in the Revel examples, but that leads to a template compliation error. Would the variable be something like $i?
For example, iterating through in Revel is done like so
{{range .messages}}
<p>{{.}}</p>
{{end}}
However, I read that the . means nil.... how does this work in Revel?
If I understand your question correctly, you can use the range built-in to get the index, and then pass it to the template like this:
{{range $i, $t := .templates}}
{{template "Template.html" $i}}
{{end}}
So if the templates variable was defined like this:
templates := []string{"One", "Two"}
and Template.html contains:
This is from Template.html: {{ . }}<br>
Then the final output will be:
This is from Template.html: 0<br>
This is from Template.html: 1<br>

Defining a top level go template

Suppose that I have tow text files (go templates):
child.tmpl
TEXT1
Hello {{ . }}
top.tmpl
TEXT2
{{ template "child.tmpl" "argument"}}
the child.tmpl template is nested in top.tmpl
A typical program to parse them will be :
package main
import (
"os"
"text/template"
)
func main() {
t := template.Must(template.ParseFiles("child.tmpl", "top.tmpl")
t.ExecuteTemplate(os.Stdout, "top.tmpl", nil)
}
Is there any method the pass the template to be embedded in the top-level template as an argument using the {{ . }} notation ?
something like {{ template {{.}} "argument" }}
More generally, what is the best way to define a layout template so I can use it like a top-level template to multiple child templates ?
There are two accepted ways to solve your problem:
The first involves writing your own template-inclusion function and registering it as an template.FuncMap with your template through template.Funcs.
The other way is to use {{define xxx}} blocks in your child templates. Then you could have two different files that define the same template:
file1.html: {{define body}}...{{end}}
file2.html: {{define body}}...{{end}}
Parse the correct file depending on your needs and in your parent template just do {{template body "argument"}}.
In my opinion, the first option is more flexible.

Resources