I'm trying to maximize code reuse across objects that share data by using nested structs. Consider the following code:
package main
import (
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
var collection *mgo.Collection
type Identifiable interface {
GetId() bson.ObjectId
}
type A struct {
Id bson.ObjectId `bson:"_id"`
A_value int
}
type B struct {
A `bson:",inline"`
B_value int
}
func (self *A) GetId() bson.ObjectId {
return self.Id
}
func setAValue(value int, a *A) {
a.A_value = value
commit(a)
}
func commit(i Identifiable) {
collection.UpsertId(i.GetId(), i)
}
func main() {
session, _ := mgo.Dial("localhost")
collection = session.DB("test").C("my_collection")
b := B{A: A{Id: bson.NewObjectId(), A_value: 1}, B_value: 2}
commit(&b)
}
At this point, the record in mongo looks like this (as I expect):
{ "_id" : ObjectId("54f0e231eefbfe049c000001"), "a_value" : 1, "b_value" : 2 }
But then I would like to do something like this in order to avoid having to write redundant functions:
setAValue(42, &b.A)
The problem is that this results in data loss as it replaces the whole entry instead of just updating it:
{ "_id" : ObjectId("54f0df4eeefbfe0474000001"), "a_value" : 42 }
Is there a way to perform an update like this without it blowing away any values that don't belong to A
? Or am I just going about this the wrong way entirely?
It's the problem in the setAValue
you commit type A, not B. Newly committed BSON value not containing B_value
.
I think you should separate set function and commit function. You may solve this set-and-commit problem via reflection or interface, but just splitting functionality is more simpler.