连接来自作为接口传递的指针的切片

时间:2018-08-01 08:27:00

标签: pointers go reflection slice

我正在为特定API的客户端工作,并建立了几种结构(每条路由一个)。
该API可与页面一起使用,因此我可以让吸气剂返回结构的切片。这是通过一个通用函数完成的,该函数采用一个接口,该接口应该是指向所需结构切片的指针,因此我可以使用Unmarshal包中的json

我面临的问题是我想在一个请求中获取所有页面,但是要做到这一点,我需要将多个切片连接起来。

我尝试使用reflect来执行此操作,但是我只能设法创建一个新切片,而无需实际更改接口指向的值。

这是我的代码的一部分:

func concatenateSlice(dst, src interface{})(){
    dstValue := reflect.ValueOf(dst)
    srcValue := reflect.ValueOf(src)
    if srcValue.Type() != dstValue.Type(){
        return
    }
    switch srcValue.Kind(){
    case reflect.Ptr, reflect.Slice:
        dstValuePoint := reflect.Indirect(dstValue)
        srcValuePoint := reflect.Indirect(srcValue)
        reflect.Copy(dstValuePoint, reflect.AppendSlice(dstValuePoint, srcValuePoint))
    }
}

对我的草率帖子感到抱歉,这是我第一次使用stackoverflow。

1 个答案:

答案 0 :(得分:0)

您不应使用reflect.Copy()复制结果切片(在追加之后),因为目标空间不足。 reflect.AppendSlice()不会更改dst所指向的片,它会在需要时分配一个新的片,并返回新的片(更确切地说是reflect.Value持有它)。

您应该做的就是简单地使用Value.Set()方法将reflect.AppendSlice()返回的切片设置为dst指向的值。要注意的一件事是您不是在设置切片指针而是在设置切片,因此首先调用例如Value.Elem(),然后致电Set()

请参见以下示例:

func concatenateSlice(dst, src interface{}) {
    dv := reflect.ValueOf(dst)
    sv := reflect.ValueOf(src)
    if dv.Type() != sv.Type() {
        return
    }

    dv2 := reflect.AppendSlice(dv.Elem(), sv.Elem())
    dv.Elem().Set(dv2)
}

测试:

dst := []int{1, 2}
src := []int{3, 4}

concatenateSlice(&dst, &src)

fmt.Println(dst)

输出(在Go Playground上尝试):

[1 2 3 4]