Dynamic template data from yaml

143 views
Skip to first unread message

Tong Sun

unread,
Oct 14, 2023, 12:33:48 PM10/14/23
to golang-nuts
Please take a look at 
https://go.dev/play/p/dTDR50dtHB0

I want to

- define my template data dynamically from yaml
- and export the yaml data if they are unexported

I.e., for the following code:

t := template.New("")
t, err = t.Parse("It's {{.A}} {{.B.C}}!\n")
if err != nil {
log.Fatalf("error: %v", err)
}
t.Execute(os.Stdout, m)

The input is `map[A:Easy! B:map[C:2 D:[3 4]]]`.
But why the template was not able to produce any output for the dynamic fields?

The error is `<.A>: can't evaluate field A in type map[main.MyKey]interface {}`
Why is that and how to fix it please?

Thanks

PS. Whole program included below:

-------------------------------------
package main

import (
"fmt"
"log"
"os"
"strings"
"text/template"

"gopkg.in/yaml.v3"
)

var data = `
a: Easy!
b:
  c: 2
  d: [3, 4]
`

type MyKey string

func (k *MyKey) UnmarshalYAML(n *yaml.Node) error {
var s string
if err := n.Decode(&s); err != nil {
return err
}
*k = MyKey(strings.ToUpper(s))
return nil
}

func main() {
m := make(map[MyKey]any)

err := yaml.Unmarshal([]byte(data), &m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m:\n%v\n\n", m)

d, err := yaml.Marshal(&m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m dump:\n%s\n\n", string(d))

t := template.New("")
t, err = t.Parse("It's {{.A}} {{.B.C}}!\n")
if err != nil {
log.Fatalf("error: %v", err)
}
err = t.Execute(os.Stdout, m)
if err != nil {
log.Fatalf("error: %v", err)
}
}
-------------------------------------

Dan Kortschak

unread,
Oct 14, 2023, 3:47:54 PM10/14/23
to golan...@googlegroups.com
On Sat, 2023-10-14 at 09:33 -0700, Tong Sun wrote:
> Please take a look at 
> https://go.dev/play/p/dTDR50dtHB0
>
> I want to
>
> - define my template data dynamically from yaml
> - and export the yaml data if they are unexported
>
> I.e., for the following code:
>
> t := template.New("")
> t, err = t.Parse("It's {{.A}} {{.B.C}}!\n")
> if err != nil {
> log.Fatalf("error: %v", err)
> }
> t.Execute(os.Stdout, m)
>
> The input is `map[A:Easy! B:map[C:2 D:[3 4]]]`.
> But why the template was not able to produce any output for the
> dynamic fields?

It is trying to match a string to a main.MyKey. If the only reason you
are using that type is to change the case of the key strings, I'd just
index into the lowercase, https://go.dev/play/p/wi9KICK1zmW.

Tong Sun

unread,
Oct 14, 2023, 4:15:37 PM10/14/23
to golang-nuts
 wow, thanks.

Hmm... somehow I had the impression that only the exported fields can be used in template as variables.

Is that a wrong impression or things have changed?


Dan Kortschak

unread,
Oct 14, 2023, 4:28:23 PM10/14/23
to golan...@googlegroups.com
On Sat, 2023-10-14 at 13:15 -0700, Tong Sun wrote:
> Hmm... somehow I had the impression that only the exported fields can
> be used in template as variables.
>
> Is that a wrong impression or things have changed?

You are indexing into a map so so the notion of fields is not relevant.

Reply all
Reply to author
Forward
0 new messages