使用带有go / mgo的嵌套结构的部分更新

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.