[GODRIVER-1657] Allow passing interface{} to Cursor.All Created: 17/Jun/20  Updated: 28/Oct/23  Resolved: 29/Jun/20

Status: Closed
Project: Go Driver
Component/s: CRUD
Affects Version/s: 1.3.4
Fix Version/s: 1.4.0

Type: Improvement Priority: Major - P3
Reporter: David Wen Riccardi-Zhu Assignee: Kriti Ravindran (Inactive)
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
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.



 Comments   
Comment by Divjot Arora (Inactive) [ 02/Jul/20 ]

Commit link: https://github.com/mongodb/mongo-go-driver/commit/3b6055918ea92e08ac2aab56b1533a30551b2c6c

Generated at Thu Feb 08 08:36:51 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.