为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
眼眸繁星 2023-08-07 15:24:02
我尝试实现一个采用(任何)结构的函数,返回这些结构的数组。ReturnArrayOfStory 用固定类型结构体类型展示了这一思想。尝试使用函数 ReturnArrayOfX 对任何类型执行相同的操作,但反射在编译时失败。package mainimport (    "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 实现我的目标?列表项 这可能吗?如果没有,为什么?
查看完整描述

2 回答

?
隔江千里

TA贡献1906条经验 获得超10个赞

您的问题有两种解决方案:


第一:如果你想使用反射返回一个类型的切片:


// You cannot return []interface{}, because this function will return [](type of x), and that is not []interface{}

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

    x1 := x

    a1 := 

// 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 *

    a1 = reflect.Append(a1.Elem(), reflect.ValueOf(x1))

    a1 = reflect.Append(a1, reflect.ValueOf(x1))

    a1 = reflect.Append(a1, reflect.ValueOf(x1))

    //return [](typeof x)

    return a1.Interface()

}

您可以将其用作:


as2 := ReturnArrayOfX(s1)

arr:=as2.([]story_t)

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

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

}

第二:你可以返回 []interface{} 而不反射:


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

   ret:=make([]interface{},0)

   ret=append(ret,x)

   ret=append(ret,x)

   ret=append(ret,x)

}

然后你需要处理数组的每个元素:


as2 := ReturnArrayOfX(s1)

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

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

    data:=as2[i].(story_t)

}


查看完整回答
反对 回复 2023-08-07
?
波斯汪

TA贡献1811条经验 获得超4个赞

这是一个通用的切片转换函数:


// convertSlice copies the slice in src to the slice pointed to by pdst. 

// The concrete values in src must be assignable to the dst elements.

func convertSlice(pdst interface{}, src interface{}) {

    dstv := reflect.ValueOf(pdst).Elem()

    srcv := reflect.ValueOf(src)

    dstv.Set(reflect.MakeSlice(dstv.Type(), srcv.Len(), srcv.Len()))

    for i := 0; i < srcv.Len(); i++ {

        dstv.Index(i).Set(reflect.ValueOf(srcv.Index(i).Interface()))

    }

}

像这样使用它:


// 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_t


var s2 []story_t

convertSlice(&s2, s1)

在操场上运行它



查看完整回答
反对 回复 2023-08-07
  • 2 回答
  • 0 关注
  • 123 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信