如何从任何结构类型派生结构列表 - 从 interface{} 获取可变长度切片

我尝试实现一个采用(任何)结构的函数,返回这些结构的数组。ReturnArrayOfStory 用固定类型结构体类型展示了这一思想。


尝试使用函数 ReturnArrayOfX 对任何类型执行相同的操作,但反射在编译时失败。


package main


import (

    "fmt"

    "reflect"

)

type story_t struct {

    LANGUAGE string

    SPECIES  string

}


func ReturnArrayOfStory(x story_t) []story_t {

    x1 := x

    var a1 []story_t

    a1 = append(a1, x1)

    a1 = append(a1, x1)

    a1 = append(a1, x1)

    return a1

}


func ReturnArrayOfX(x interface{}) []interface{} {

    x1 := x

    v1 := reflect.ValueOf(&x1).Elem()

    a1 := []reflect.TypeOf(&x1)

    //  var a1 []x

    a1 = append(a1, x1)

    a1 = append(a1, x1)

    a1 = append(a1, x1)

    //return a1

    return a1

}


func main() {


    var as1 []story_t


    s1 := story_t{"EN", "Prince of Persia"}


    as1 = ReturnArrayOfStory(s1)

    //as1 := ReturnArrayOfX(s1)

    for i := 0; i < len(as1); i++ {

        fmt.Printf("%02d %+v\n", i, as1[i])

    }


    as2 := ReturnArrayOfX(s1)

    //as1 := ReturnArrayOfX(s1)

    for i := 0; i < len(as2); i++ {

        fmt.Printf("%02d %+v\n", i, as2[i])

    }


}


a1 := []reflect.TypeOf(&x1)

main.go:25:8: reflect.TypeOf is not a type

这是一个简化的场景。实际上,我喜欢从数据库等外部数据源读取多种结构类型。


我怎样才能通过 ReturnArrayOfX 实现我的目标?

列表项 这可能吗?如果没有,为什么?


眼眸繁星
浏览 125回答 2
2回答

隔江千里

您的问题有两种解决方案:第一:如果你想使用反射返回一个类型的切片:// You cannot return []interface{}, because this function will return [](type of x), and that is not []interface{}func ReturnArrayOfX(x interface{}) interface{} {&nbsp; &nbsp; x1 := x&nbsp; &nbsp; a1 :=&nbsp;// this creates *[](typeOf x)reflect.New(reflect.SliceOf(reflect.TypeOf(x)))// Append the first element to *[](typeof x)// after this, a1 now points to a slice, not to a slice *&nbsp; &nbsp; a1 = reflect.Append(a1.Elem(), reflect.ValueOf(x1))&nbsp; &nbsp; a1 = reflect.Append(a1, reflect.ValueOf(x1))&nbsp; &nbsp; a1 = reflect.Append(a1, reflect.ValueOf(x1))&nbsp; &nbsp; //return [](typeof x)&nbsp; &nbsp; return a1.Interface()}您可以将其用作:as2 := ReturnArrayOfX(s1)arr:=as2.([]story_t)for i := 0; i < len(arr); i++ {&nbsp; &nbsp; fmt.Printf("%02d %+v\n", i, arr[i])}第二:你可以返回 []interface{} 而不反射:func ReturnArrayOfX(x interface{}) []interface{} {&nbsp; &nbsp;ret:=make([]interface{},0)&nbsp; &nbsp;ret=append(ret,x)&nbsp; &nbsp;ret=append(ret,x)&nbsp; &nbsp;ret=append(ret,x)}然后你需要处理数组的每个元素:as2 := ReturnArrayOfX(s1)for i := 0; i < len(as2); i++ {&nbsp; &nbsp; fmt.Printf("%02d %+v\n", i, as2[i])&nbsp; &nbsp; data:=as2[i].(story_t)}

波斯汪

这是一个通用的切片转换函数:// convertSlice copies the slice in src to the slice pointed to by pdst.&nbsp;// The concrete values in src must be assignable to the dst elements.func convertSlice(pdst interface{}, src interface{}) {&nbsp; &nbsp; dstv := reflect.ValueOf(pdst).Elem()&nbsp; &nbsp; srcv := reflect.ValueOf(src)&nbsp; &nbsp; dstv.Set(reflect.MakeSlice(dstv.Type(), srcv.Len(), srcv.Len()))&nbsp; &nbsp; for i := 0; i < srcv.Len(); i++ {&nbsp; &nbsp; &nbsp; &nbsp; dstv.Index(i).Set(reflect.ValueOf(srcv.Index(i).Interface()))&nbsp; &nbsp; }}像这样使用它:// Convert []story_t to []interface{}s0 := []story_t{{"EN", "Prince of Persia"}, {"EN", "Karateka"}}var s1 []interface{}convertSlice(&s1, s0)// Convert []interface{} containing story_t to []story_tvar s2 []story_tconvertSlice(&s2, s1)在操场上运行它。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go