>

서비스간에 공유하기 위해 몇 가지 일반적인 방법 (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)))
}

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) 와 같은 접근법을 얻는 것입니다  (위에서 볼 수 있습니다)


  • 답변 # 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 nil
    }
    
    

    다음과 같이 부르십시오 :

    var data []*T
    err := 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 nil
    }
    
    

관련 자료

  • 이전 (spring boot 2) javalangillegalstateexception - applicationcontex를로드하지 못했습니다
  • 다음 Python, CSV, Quandl API