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

huangapple go评论82阅读模式
英文:

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

问题

我想创建一个通用的模型结构体,嵌入到使用gorp(https://github.com/coopernurse/gorp)在MySQL数据库中持久化对象的结构体中。据我了解,在Go中,这种组合是实现类似于强类型面向对象语言中继承的方式。

然而,我一直没有好运气,因为我想在GorpModel结构体上定义所有的CRUD方法,以避免在每个模型中重复定义它们,但是这会导致gorp(目前我正在使用的方式)假设我要与之交互的表名为GorpModel,这是由于gorp使用的反射引起的。这自然会导致错误,因为在我的数据库中没有这样的表。

有没有办法找出/使用我所在的类型(GorpModel嵌入的超类),使下面的代码工作,或者我完全走错了方向?

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)
    } 
}

GorpModel结构体的New属性用于跟踪它是否是新创建的模型,以及我们是否应该在Save上调用UpdateInsert(目前在子User结构体中定义)。

英文:

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).

答案1

得分: 2

没有。

我不知道最佳的解决方案是什么,但是关于你试图在某种基类中实现的CRUD操作,只需将它们编写为函数即可。例如:

func Create(gm interface{}) { // 或者其他应该是什么签名
    err := dbm.Insert(gm)
    if err != nil {
        panic(err)
    }
}
英文:

> 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)
    }
}

huangapple
  • 本文由 发表于 2013年4月22日 01:03:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/16133813.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定