Un miembro _id ya no se asigna al tipo ObjectId, cuando su tipo solo se deriva de bson.ObjectId:
import ( "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" ) type CustomId bson.ObjectId type Foo struct { ID1 CustomId `bson:"_id"` // broken ID2 bson.ObjectId // mapped as expected } func main() { session, _ := mgo.Dial("127.0.0.1") coll := session.DB("mgodemo").C("foocoll") doc := Foo{ CustomId(bson.NewObjectId()), bson.NewObjectId(), } coll.Insert(doc) }El _id debería haber sido un ObjectId en Mongo. Pero resulta que se eligió la cadena :
Concha Mongo:
> db.foocoll.findOne() { "_id" : "XvMn]K� �\f:�", "id2" : ObjectId("58764d6e5d4be120fa0c3ab1") } // id2 is OK ... > typeof db.foocoll.findOne()._id string // OOps. Should be ObjectId !Esto puede ser intencionado, ya que bson.ObjectId se deriva de string . Pero aquí, es malo para nosotros.
¿Podemos decirle a mgo que asigne el _id a ObjectId en la base de datos?
Use las interfaces Setter y Getter para controlar la representación en mongo:
type CustomId bson.ObjectId func (id *CustomId) SetBSON(raw bson.Raw) error { var v bson.ObjectId err := raw.Unmarshal(&v) *id = CustomId(v) return err } func (id CustomId) GetBSON() (interface{}, error) { return bson.ObjectId(id), nil }Cuando haces esto:
type CustomId bson.ObjectId Está creando un nuevo tipo y el paquete mgo ya no lo verá/reconocerá como bson.ObjectId (el tipo bson.ObjectId está "codificado" en el paquete bson). El nuevo tipo tendrá 0 métodos.
Me limitaría a bson.ObjectId . Pero si aún desea un tipo de ID personalizado, puede usar la incrustación al crear su CustomId : incruste un valor de tipo bson.ObjectId y use la bandera bson inline para el campo ID1 :
type CustomId struct { bson.ObjectId `bson:"_id"` } type Foo struct { ID1 CustomId `bson:",inline"` ID2 bson.ObjectId }Usándolo:
doc := Foo{ CustomId{bson.NewObjectId()}, bson.NewObjectId(), } Esto tiene la ventaja de que CustomId tendrá todos los métodos que tiene bson.ObjectId , y puede agregar otros nuevos y "anular" los métodos existentes.
Otra opción sería usar un tipo de interfaz (por ejemplo interface{} ) para su CustomId , usarlo sería mucho más "simple":
type CustomId interface{} type Foo struct { ID1 CustomId `bson:"_id"` ID2 bson.ObjectId // mapped as expected }Usándolo:
doc := Foo{ bson.NewObjectId(), bson.NewObjectId(), } Por supuesto, si sigue este camino, debe usar el tipo de afirmación , en caso de que necesite acceder al bson.ObjectId envuelto de CustomId .