go - 如果传入的数组为 &val 然后转换为接口(interface){},则更新数组元素

标签 go

我正在尝试编写一些通用方法(CRUD 方法)以在我的服务之间共享它。以下示例是一个 GetAll() 方法,它返回我的集合中存在的所有文档:

func GetAll(out interface{}) error {
    // mongodb operations

    // iterate through all documents
    for cursor.Next(ctx) {
        var item interface{}
        // decode the document
        if err := cursor.Decode(&item); err != nil {
            return err
        }
        (*out) = append((*out), item)
        // arrays.AppendToArray(out, item) // Read below :)
    }

    return nil // if no error

}

我也尝试过一些反射(reflection),但随后:

package arrays

import "reflect"

func AppendToArray(slicePtrInterface interface{}, item interface{}) {
    // enter `reflect`-land
    slicePtrValue := reflect.ValueOf(slicePtrInterface)
    // get the type
    slicePtrType := slicePtrValue.Type()
    // navigate from `*[]T` to `T`
    _ = slicePtrType.Elem().Elem() // crashes if input type not `*[]T`
    // we'll need this to Append() to
    sliceValue := reflect.Indirect(slicePtrValue)
    // append requested number of zeroes
    sliceValue.Set(reflect.Append(sliceValue, reflect.ValueOf(item)))
}

panic: reflect.Set: value of type primitive.D is not assignable to type *mongodb.Test [recovered] panic: reflect.Set: value of type primitive.D is not assignable to type *mongodb.Test

我想要的是获得与 cursor.Decode(&item) 相同的方法(您可以在上面看到)

最佳答案

方法如下:

// GetAll decodes the cursor c to slicep where slicep is a 
// pointer to a slice of pointers to values.
func GetAll(ctx context.Context, c *Cursor, slicep interface{}) error {
    // Get the slice. Call Elem() because arg is pointer to the slice.
    slicev := reflect.ValueOf(slicep).Elem()

    // Get value type. First call to Elem() gets slice 
    // element type. Second call to Elem() dereferences 
    // the pointer type.
    valuet := slicev.Type().Elem().Elem()

    // Iterate through the cursor...
    for c.Next(ctx) {
        // Create new value.
        valuep := reflect.New(valuet)

        // Decode to that value.
        if err := c.Decode(valuep.Interface()); err != nil {
            return err
        }

        // Append value pointer to slice.
        slicev.Set(reflect.Append(slicev, valuep))
    }
    return c.Err()
}

这样调用它:

var data []*T
err := GetAll(ctx, c, &data)
if err != nil {
   // handle error
}

Run it on the Go Playground .

下面是使用非指针 slice 元素的代码的概括:

func GetAll(ctx context.Context, c *Cursor, slicep interface{}) error {
    slicev := reflect.ValueOf(slicep).Elem()
    valuet := slicev.Type().Elem()
    isPtr := valuet.Kind() == reflect.Ptr
    if isPtr {
        valuet = valuet.Elem()
    }
    for c.Next(ctx) {
        valuep := reflect.New(valuet)
        if err := c.Decode(valuep.Interface()); err != nil {
            return err
        }
        if !isPtr {
            valuep = valuep.Elem()
        }
        slicev.Set(reflect.Append(slicev, valuep))
    }
    return c.Err()
}

关于go - 如果传入的数组为 &val 然后转换为接口(interface){},则更新数组元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57023943/

相关文章:

go - 如何在 go protobuf 中获取具体类型的 slice (不是指针)

json - 如何在 JSON 文件中设置新日期

Golang - echo api 中的绑定(bind) header

json - 用于在 JSON 中上传文件的 REST API

http - 如何使用 golang 发送帖子,用这个 curl 命令替换

c - Go 中的动态 FFI

当我执行这个 go 代码时,html 代码显示没有 css,但是当我直接在浏览器中打开它时,它显示 html 和 css 都很好

function - os.O_TRUNC 的作用是什么?

Golang 的 bool 类型

go - 使用 goroutines 处理并发的 neo4j 连接