I understand map key/value is not stored in sequence order so I expect when I loop map key using range in text/template, the output value should be random. However, the following code always gives me the output of
1
2
3
I expect it can be 1/2/3 or 3/2/1 or 1/3/2 as random pattern?
If you read the text/template package docs, you’ll see that for maps, if it’s keys are able to be sorted, it will be:
{{range pipeline}} T1 {{end}}
The value of the pipeline must be an array, slice, map, or channel.
If the value of the pipeline has length zero, nothing is output;
otherwise, dot is set to the successive elements of the array,
slice, or map and T1 is executed. If the value is a map and the
keys are of basic type with a defined order ("comparable"), the
elements will be visited in sorted key order.
One other thing if you actually want to use a map and keep it random, is you can just create a function that outputs the map and then use that function from within your template.
For example these results will be different now and then:
package main
import (
"html/template"
"log"
"os"
"strconv"
)
const (
tmpl = `{{ randomMap . }}`
)
func randomMap(m map[string]int) string {
output := ""
for k, v := range m {
output += fmt.Sprintf("%s: %d\n", k, v)
}
return output
}
func main() {
m := map[string]int{
"bbb": 2, "aaa": 1, "ccc": 3,
}
fncs := template.FuncMap{
"randomMap": randomMap,
}
t := template.Must(template.New("").Funcs(fncs).Parse(tmpl))
err := t.Execute(os.Stdout, m)
if err != nil {
log.Fatalln(err)
}
}
(Just be aware if you try this in the Go playground, the results will stay the same because of caching, but locally the results will differ)