ZenLikeThat
ZenLikeThat

Reputation: 2062

Golang: Is there any way to access the "child" struct in the "parent" struct's methods in Go's composition model?

I want to make a generic model struct to embed in structs that will use gorp (https://github.com/coopernurse/gorp) to persist objects in my MySQL database. It's my understanding that this kind of composition is how one accomplishes things in Go that are done with inheritance in strongly OO languages.

I haven't been having good luck, however, as I want to define all of the CRUD methods on the GorpModel struct, to avoid repeating them in each model, but this causes gorp (as I'm using it right now) to assume that the table I want to interact with is called GorpModel due to the reflection that gorp uses. Which causes errors, naturally, as I have no such table in my database.

Is there any way to figure out / use which type I'm in (the superclass which GorpModel is embedded in) to make the below code work, or am I barking up the wrong tree altogether?

package models

import (
    "fmt"
    "reflect"
    "github.com/coopernurse/gorp"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

type GorpModel struct {
    New            bool   `db:"-"`
}

var dbm *gorp.DbMap = nil

func (gm *GorpModel) DbInit() {
    gm.New = true
    if dbm == nil {
        db, err := sql.Open("mysql", "username:password@my_db")
        if err != nil {
            panic(err)
        } 
        dbm = &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{"InnoDB", "UTF8"}}
        dbm.AddTable(User{}).SetKeys(true, "Id")
        dbm.CreateTables()
    }           
}

func (gm *GorpModel) Create() {
    err := dbm.Insert(gm)
    if err != nil {
        panic(err)
    }
}

func (gm *GorpModel) Delete() int64 {
    nrows, err := dbm.Delete(gm)
    if err != nil {
        panic(err)
    }

    return nrows
}   

func (gm *GorpModel) Update() {
    _, err := dbm.Update(gm)
    if err != nil {
        panic(err)
    } 
}   

The New property of the GorpModel struct is used to keep track of whether it is a newly created model, and whether we should call Update or Insert on Save (which is defined in the child User struct at the moment).

Upvotes: 2

Views: 2972

Answers (1)

cthom06
cthom06

Reputation: 9645

Is there any way to figure out / use which type I'm in (the superclass which GorpModel is embedded in)

No.

I don't know the best way to structure your solution, but with respect to the CRUD you're trying to implement in some kind of base class, just write them as functions. ie.

func Create(gm interface{}) { // or whatever the signature should be
    err := dbm.Insert(gm)
    if err != nil {
        panic(err)
    }
}

Upvotes: 2

Related Questions