无法在 Go 中将 []interface{} 转换为 []string
Can't convert []interface{} to []string in Go
XY 问题: 我正在尝试读取如下所示的 YAML 文件,并输出一组组合了 YAML 文件中某些键和值的元组.例如。鉴于此 YAML 数据:
---
fruit:
apple:
colour:
- green
'banana':
colour:
- yellow
pear:
colour:
- green
- yellow
我想将“水果”下的每个键与“颜色”下的每个值组合成元组。我的元组看起来像这样:
apple:green
banana:yellow
pear:green
pear:yellow
为此,我使用映射[string]接口{}将我的 YAML 数据解组为 Go - 我不能使用结构,因为“fruit”下面的键的名称可能是任何东西,所以我需要使用动态类型。到目前为止,这是我的代码:
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)
}
}
}
}
游乐场link:https://go.dev/play/p/v8iuzmMLtjX
问题是 for colour := range colours
- 我收到错误:
cannot range over colours (type interface {})
我发现 说我不能直接将 []interface{} 转换为 []string,而必须迭代这些值。这就是我在这里尝试做的。 v2
变量计算出 map[string]interface {}
类型,例如可以是 map[colour:[green yellow]]
。然后我尝试将其转换为另一个 map[string]interface{} 以获得“颜色”的值,它计算出 []interface{} 类型 [green yellow]
并存储在 colours
变量。
但出于某种原因我无法遍历 colours
。我不明白我的解决方案和 icza's solution in the linked answer(我已经 link编辑了他们的 Playground link)有什么不同。 colours
在我的解决方案中的数据类型是 []interface{},在 icza 的解决方案中 t
的数据类型也是 []interface{} - 但在这种情况下可以迭代切片并访问其中的值。
我尝试的另一个解决方案来自 ,它尝试直接将 []interface{} 转换为 []string:
c := colours.([]string)
那也没有用:
panic: interface conversion: interface {} is []interface {}, not []string
我需要做什么才能使这个解决方案起作用?
因为在编译时只有映射的键是未知的,但是结构是已知的,所以你可以比map[string]interface{}
:
更具体
type Document struct {
Fruits map[string]Fruit `yaml:"fruit"`
}
type Fruit struct {
Colours []string `yaml:"colour"`
}
这使得建立您的价值观变得微不足道:
package main
import (
"fmt"
"gopkg.in/yaml.v3"
)
var data string = `
---
fruit:
apple:
colour:
- green
'banana':
colour:
- yellow
pear:
colour:
- green
- yellow
`
func main() {
var m Document
yaml.Unmarshal([]byte(data), &m)
for name, fruit := range m.Fruits {
for _, colour := range fruit.Colours {
fmt.Printf("%s:%s\n", name, colour)
}
}
}
感谢 Cerise Limón 提供的更正帮助我修正了我的解决方案!
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"]
c := colours.([]interface{})
for _, colour := range c {
cs := colour.(string)
fmt.Printf("%v:%v\n", fruit, cs)
}
}
}
}
XY 问题: 我正在尝试读取如下所示的 YAML 文件,并输出一组组合了 YAML 文件中某些键和值的元组.例如。鉴于此 YAML 数据:
---
fruit:
apple:
colour:
- green
'banana':
colour:
- yellow
pear:
colour:
- green
- yellow
我想将“水果”下的每个键与“颜色”下的每个值组合成元组。我的元组看起来像这样:
apple:green
banana:yellow
pear:green
pear:yellow
为此,我使用映射[string]接口{}将我的 YAML 数据解组为 Go - 我不能使用结构,因为“fruit”下面的键的名称可能是任何东西,所以我需要使用动态类型。到目前为止,这是我的代码:
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)
}
}
}
}
游乐场link:https://go.dev/play/p/v8iuzmMLtjX
问题是 for colour := range colours
- 我收到错误:
cannot range over colours (type interface {})
我发现 v2
变量计算出 map[string]interface {}
类型,例如可以是 map[colour:[green yellow]]
。然后我尝试将其转换为另一个 map[string]interface{} 以获得“颜色”的值,它计算出 []interface{} 类型 [green yellow]
并存储在 colours
变量。
但出于某种原因我无法遍历 colours
。我不明白我的解决方案和 icza's solution in the linked answer(我已经 link编辑了他们的 Playground link)有什么不同。 colours
在我的解决方案中的数据类型是 []interface{},在 icza 的解决方案中 t
的数据类型也是 []interface{} - 但在这种情况下可以迭代切片并访问其中的值。
我尝试的另一个解决方案来自
c := colours.([]string)
那也没有用:
panic: interface conversion: interface {} is []interface {}, not []string
我需要做什么才能使这个解决方案起作用?
因为在编译时只有映射的键是未知的,但是结构是已知的,所以你可以比map[string]interface{}
:
type Document struct {
Fruits map[string]Fruit `yaml:"fruit"`
}
type Fruit struct {
Colours []string `yaml:"colour"`
}
这使得建立您的价值观变得微不足道:
package main
import (
"fmt"
"gopkg.in/yaml.v3"
)
var data string = `
---
fruit:
apple:
colour:
- green
'banana':
colour:
- yellow
pear:
colour:
- green
- yellow
`
func main() {
var m Document
yaml.Unmarshal([]byte(data), &m)
for name, fruit := range m.Fruits {
for _, colour := range fruit.Colours {
fmt.Printf("%s:%s\n", name, colour)
}
}
}
感谢 Cerise Limón 提供的更正帮助我修正了我的解决方案!
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"]
c := colours.([]interface{})
for _, colour := range c {
cs := colour.(string)
fmt.Printf("%v:%v\n", fruit, cs)
}
}
}
}