XY problem: I'm trying to read in a YAML file such as the one below, and output a set of tuples that combine certain keys and values from the YAML file. E.g. given this YAML data:
--- fruit: apple: colour: - green 'banana': colour: - yellow pear: colour: - green - yellow I want to combine each key under "fruit" with each value under "colour" into tuples. My tuples would look like this:
apple:green banana:yellow pear:green pear:yellow To do this, I'm using a map[string]interface{} to Unmarshal my YAML data into Go - I can't use a struct because the names of the keys below "fruit" could be anything, so I need to use a dynamic type. This is my code so far:
package main import ( "fmt" "log" "gopkg.in/yaml.v3" ) var data string = ` --- fruit: apple: colour: - green 'banana': colour: - yellow pear: colour: - green - yellow ` func main() { m := make(map[string]interface{}) err := yaml.Unmarshal([]byte(data), &m) if err != nil { log.Fatal("Failed to parse YAML file") } for _, v := range m { fruits := v.(map[string]interface{}) for fruit, v2 := range fruits { colours := v2.(map[string]interface{})["colour"] for colour := range colours { fmt.Println("%v:%v\n", fruit, colour) } } } } Playground link: https://go.dev/play/p/v8iuzmMLtjX
The problem is for colour := range colours - I get the error:
cannot range over colours (type interface {}) I found this answer to a similar question which says that I cannot directly convert a []interface{} to []string, and must instead iterate over the values. That's what I've tried to do here. The v2 variable works out to a map[string]interface {} type, which for example could be map[colour:[green yellow]]. Then I've tried converting that into another map[string]interface{} to get the value of "colour", which works out to a []interface{} type [green yellow] and is stored in the colours variable.
But I can't iterate over colours for some reason. I don't understand what's different about my solution and icza's solution in the linked answer (I've linked their Playground link). The data type of colours in my solution is []interface{}, and in icza's solution the data type of t is also []interface{} - but in that case it is possible to iterate through the slice and access the values within.
Another solution I tried was from this answer to a different question, which was to try directly converting the []interface{} to a []string:
c := colours.([]string) That also didn't work:
panic: interface conversion: interface {} is []interface {}, not []string What do I need to do to make this solution work?
map[string]interface{}: go.dev/play/p/Le00DlzOz8T. This should make it trivial to build your values.for colour := range c { cs := colour.(string) }-->invalid type assertion: colour.(string) (non-interface type int on left). Still trying to work out why it thinks I'm converting to an int.