【问题标题】:Concatenate slices from pointer passed as interface从作为接口传递的指针连接切片
【发布时间】:2019-01-08 18:02:28
【问题描述】:

我正在开发一个特定 API 的客户端,并且我构建了多个结构(每个路由一个结构)。
API 适用于页面,因此我有 getter 返回结构的切片。这是通过一个通用函数完成的,该函数接受一个接口,该接口应该是指向所需结构切片的指针,因此我可以使用 json 包中的 Unmarshal

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

我尝试使用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。

【问题讨论】:

    标签: pointers go reflection slice


    【解决方案1】:

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

    您应该做的是将reflect.AppendSlice() 返回的切片设置为dst 指向的值,只需使用Value.Set() 方法即可。需要注意的一点是,您设置的不是切片指针而是切片,因此首先调用例如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]
    

    【讨论】:

    • 非常感谢这解决了我的问题并帮助我更好地理解reflect pkg!
    猜你喜欢
    • 2016-10-27
    • 2016-07-17
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 2017-07-04
    • 2018-05-30
    • 2019-01-05
    • 1970-01-01
    相关资源
    最近更新 更多