猿问

如果数组作为 &val 传递然后转换为 interface{},则更新数组元素

我正在尝试编写一些通用方法(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


}

我也尝试过一些反思,但后来:


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)))

}

恐慌:reflect.Set:类型primitive.D的值不可分配给类型*mongodb.Test [已恢复] 恐慌:reflect.Set:类型primitive.D的值不可分配给类型*mongodb.Test


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


MM们
浏览 91回答 1
1回答

潇潇雨雨

操作方法如下:// 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 []*Terr := GetAll(ctx, c, &data)if err != nil {   // handle error}在 Go Playground 上运行它。以下是处理非指针切片元素的代码的概括: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()}
随时随地看视频慕课网APP

相关分类

Go
我要回答