sprig
sprig copied to clipboard
keys function does not work with map[string]struct
I want to get the string keys of a dict which is a map[string]string (or anything different from map[string]interface.
Ex script:
package main
import (
"html/template"
"os"
"github.com/Masterminds/sprig/v3"
)
func main() {
// Define your data, a map[string]interface{} in this case
data := map[string]interface{}{
"MyMap": map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
}
// Create a new template and add Sprig functions
tmpl, err := template.New("example").Funcs(sprig.FuncMap()).Parse(`
Sprig Keys Example
Keys of MyMap:
{{ range $key := .MyMap | keys }}
{{ $key }}
{{ end }}
`)
if err != nil {
panic(err)
}
// Execute the template with the data
err = tmpl.Execute(os.Stdout, data)
if err != nil {
panic(err)
}
}
This gives an error:
panic: template: example:4:28: executing "example" at <keys>: wrong type for value; expected map[string]interface {}; got map[string]string
I consider that a bug... keys shouldn't care of the values, only the keys... An I missing something ?
I made it work uing the ugliest thing... please let me know if there's a better solution. This example uses map[string]string, but I actually use a map[string]*my-own-struct` so I need to support many types and pointers...
package main
import (
"encoding/json"
"html/template"
"log"
"os"
"github.com/Masterminds/sprig/v3" // Import Sprig
)
func main() {
// Define your data, a map[string]interface{} in this case
data := map[string]interface{}{
"MyMap": map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
}
// Create a new template and add Sprig functions
tmpl, err := template.New("example").Funcs(sprig.FuncMap()).Parse(`
Sprig Keys Example
Keys of MyMap:
{{- range $key := .MyMap | keys }}
{{ $key }}
{{- end -}}
`)
if err != nil {
panic(err)
}
// Execute the template with the data
// Marshall the values inside data
jsonData, err := json.Marshal(data)
if err != nil {
log.Fatal(err)
}
// Unmarshall it into a map[string]any
var result map[string]any
err = json.Unmarshal(jsonData, &result)
if err != nil {
log.Fatal(err)
}
// Use the unmarshalled data instead of original data
data = result
err = tmpl.Execute(os.Stdout, result)
if err != nil {
panic(err)
}
}