Uploaded image for project: 'Go Driver'
  1. Go Driver
  2. GODRIVER-1657

Allow passing interface{} to Cursor.All

    XMLWordPrintable

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Fixed
    • Affects Version/s: 1.3.4
    • Fix Version/s: 1.4.0
    • Component/s: CRUD
    • Security Level: Public
    • Labels:
      None
    • Environment:
      Linux x86_64
      go 1.14.4

      Description

      Passing an interface{} to cursor.All results in a panic.

       

      panic: reflect: Elem of invalid type interface {} [recovered]
       panic: reflect: Elem of invalid type interface {}
      goroutine 14 [running]:
      // ...
      reflect.(*rtype).Elem(0x97e6c0, 0xc00022bae8, 0x194)
       /usr/lib/go/src/reflect/type.go:912 +0x198
      go.mongodb.org/mongo-driver/mongo.(*Cursor).All(0xc0003c1400, 0xb7f340, 0xc000024110, 0x945f80, 0xc00022bae8, 0x0, 0x0)
       /home/dwrz/.go/pkg/mod/go.mongodb.org/mongo-driver@v1.3.4/mongo/cursor.go:183 +0x15d
      
      

       

      It would be great if cursor.All could unwrap the type underlying the interface{}, just like pipeline.All in mgo.

      Compare:
      https://github.com/mongodb/mongo-go-driver/blob/v1.3.4/mongo/cursor.go#L183
      https://github.com/globalsign/mgo/blob/master/session.go#L4436.

      For background:

      We usually wrap our DB driver in a package. We do this for a few reasons: to set defaults, add logging, and make contributing a little easier for engineers that are not full-time Go / backend engineers.

      With mgo, we were able to have Aggregate and Find functions that accepted an interface parameter, and then forwarded that parameter to pipeline.All.

      We are unable to do this with the official driver, which seems to be written with the expectation that the type will be passed in directly from the caller.

      I'm not a frequent user of reflect, but it seems I can implement the desired functionality by adding the following before line 183 in cursor.go:

      if sliceVal.Kind() == reflect.Interface {
        sliceVal = sliceVal.Elem()
      }
      if sliceVal.Kind() != reflect.Slice {}}
       panic("results argument must be a pointer to a slice"")
      }
      

      This is pretty much the same code used in mgo's pipeline.All. With this code, my wrapper function is able to decode the passed in interface.

        Attachments

          Activity

            People

            Assignee:
            kriti.ravindran Kriti Ravindran (Inactive)
            Reporter:
            davidwen.riccardizhu@gooduncle.com David Wen Riccardi-Zhu
            Participants:
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: