如何将接口转换为接口切片?

  • 本文关键字:接口 切片 转换 go
  • 更新时间 :
  • 英文 :


我的输入是一个interface{},我知道它可以是任何类型的数组。

我想读取输入的元素之一,所以我尝试将我的interface{}转换为[]interface{},但 go 会给我以下错误:

panic:接口转换:接口 {} 是 []

map[string]int,而不是 []接口 {}

如何进行转换?(如果可能,不反映(。

游乐场测试

谢谢

涉及reflect包的解决方案。

package main
import (
"fmt"
"reflect"
)
func main() {
var v interface{} = []string{"a", "b", "c"}
var out []interface{}
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Slice {
for i := 0; i < rv.Len(); i++ {
out = append(out, rv.Index(i).Interface())
}
}
fmt.Println(out)
}
// Output:
// [a b c]

我现在实际上正在研究这个问题,因为我的问题涉及从 json 对象 (map[string]interface{}( 中获取一些东西,该对象可能包含也可能不包含特定键({"someKey":[a, b, c, ...](,如果它确实包含该键,那么我们希望获取该键(必然是接口{}类型(并将其转换为[]interface{}。到目前为止,我发现的方法是使用 json marshall/unmarshall。这对我来说似乎有点笨拙,如果我找到更优雅的解决方案,就会更新。直到那时,你可以有我的方法: https://play.golang.org/p/4VAwQQE4O0b

type a map[string]interface{}
type b []string
func main() {
obj := a{
"someKey": b{"a", "b", "c"},
}
if obj["someKey"] != nil { // check the value exists
var someArr []interface{}
//marshal interface to byte and then unmarshal to []interface{}
somebytes, _ := json.Marshal(obj["someKey"])
err := json.Unmarshal(somebytes, &someArr)
if err != nil {
fmt.Println("Error in unmarshal")
}
fmt.Println(someArr)
}
}

如何进行转换?(如果可能,不反映(。

请考虑类型开关。

反射是昂贵的。

func toSlice(i interface{}) []interface{} {
var out []interface{}
switch v := i.(type) {
case []interface{}:
for x := 0; x < len(v); x++ {
out = append(out, v[x])
}
default:
fmt.Printf("invalid type: %Tn", v)
}
return out
}

接口的要点是定义要使用的行为,如果使用空接口,则对该切片中的类型一无所知。

如果要打印它,可以使用println或printf而不进行转换。

如果要访问它,并且必须允许任何类型,则可以使用反射(使用缓慢且复杂(。

如果你想使用它,并使用你可以定义函数的常见行为/数据,定义一个接口,例如:

type Doer interface {
Do() error
}
parentStruct := []Doer{...}
testStruct.Do()

如果这些都不起作用,请等待 Go 2 和泛型。

对于在 2022 年发现这种情况的任何人,现在我们有泛型,您可以这样做:

func convertSlice[T any](data []T) []interface{} {
output := make([]interface{}, len(data))
for idx, item := range data {
output[idx] = item
}
return output
}

我认为您正在寻找的是类型断言

package main
import (
"fmt"
)
func main() {
parentStruct := map[string]interface{}{
"test": []map[string]int{
{"a": 1, "b": 2},
{"c": 3},
},
}
testStruct := parentStruct["test"].([]map[string]int)
fmt.Println(testStruct)
}

阅读此链接: https://golang.org/ref/spec#Type_assertions

https://play.golang.org/p/81uL2hgrN3l

最新更新