当避免全局变量(/ state)时,我发现自己将对象向后链接到其父级。 我这样做对吗? 如果不解释为什么? 还有其他?

Note: Im just picking the current struct/example to explain the problem.

type MsgBoxFactory struct{
    db *dbSql //contains conn-pool and other DB related settings/flags
}

func (f *MsgBoxFactory) NewMsgBox(userId string) {
    return MsgBox{userId, f.db} //f.db link is inevitable
}

type MsgBox struct {
    ownerId string
    db *dbSql
}

func (m *MsgBox) NewMessage(content string) *Message {
    return Message{content, *m.dbSql} //m.dbSql link is inevitable
}

type Message struct {
    content string
    //other fields such as recipents, isRead, created time etc.

    db *dbSql
}

func (m *Message) Send(to string) {
    message.to = to  //just imagine this saves the message to database.
    m.db.Save(message)
}

I tend to call this "backward-referencing"[i don't know actual name]... Is this the only way? Previously i was "backward-referencing" entire parent objects. Now i find myself "backward-referencing" objects such as config/dbconn etc...

Is this a good way? what is better?

Oh i have also tried closure to get rid of it atleast from view.

type Message Struct{
    content string

    Send func(string) error // the problem is `json:"-"` needs to be added. Else the objects are not json compatible
}

func (m *MsgBox) NewMsg(content string) *Message {
    msg := &Message{ content }
    msg.Send = func(to string) error {
        return m.db.Save(msg)
    }
}

Basically the code looks almost equally cluttered with unnecessary complexity/code

EDIT: The question is not specific to go. Just posted it because i use go. Any tag suggestion is appreciated to open the question for wider community.

I usually implement a model helper relationship.

Where MsgBox is your model which has all the data specific elements (No DB related elements).

The MsgBoxHelper does all your database related work. (i.e.

err := MsgBoxHelper.Save(MsgBox)
msgBox, err := MsgBoxHelper.Load(Key)

)

Edit:

The advantage with this method is it decouples your Model from the datastore, which should inturn make it easier should you wish to change your underlying technology (Which doesn't often happen). In practice it's more useful should you start doing things like caching.

If generically you are referencing other structures within your model i.e.

type MsgBox struct {
    Colour *MsgBoxColour
    ...
}

type MsgBoxColor struct {
    ID int
    ...
}

then when you load the Model in your MsgBoxHelper you call the MsgBoxColourHelper with the ID you stored in the MsgBoxColour table, this then returns your MsgBoxColour that you then associate with the returning MsgBox.