如何为golang中具有一个公共字段的不同结构添加方法

时间:2015-11-11 01:19:27

标签: go beego

我正在使用beego / orm作为我的应用程序。这里我有2个模型

type ModelA struct {
    Guid string `orm:"pk"`
    FiledA string
}

type ModelB struct {
    Guid string `orm:"pk"`
    FiledB string
}

我需要为每个结构添加Save()方法。一般来说,我可以创建一个Base结构并将其混合到ModelAModelB中,但是orm不起作用。

有没有更好的解决方案?

edit1 :在此处提供Save()代码,使问题更加清晰

func (this *ModelA) Save() error {
    o := orm.NewOrm()
    guid := guidlib.Generate()
    this.Guid = guid
    _, err := o.Insert(this)
    return err
}

func (this *ModelB) Save() error {
    o := orm.NewOrm()
    guid := guidlib.Generate()
    this.Guid = guid
    _, err := o.Insert(this)
    return err
}

2 个答案:

答案 0 :(得分:4)

是。定义一个接口。另外,讨厌挑剔,虽然我很确定你正在谈论嵌入那里并不是一个混合因素。 Go中存在的概念。这是一些演示构造的伪代码。

type Savable interface {
       Save()
}

// satisfies Savable for ModelA
func (a ModelA) Save() {
      // do something
}

var i Savable
i = SomeMethodThatRetunsMyModel()
i.Save()
SomeOthermMethodThatAcceptsASavableAndCallesSave(i)
编辑:根据一些讨论,似乎OP可能想要做类似下面的事情

type ModelA struct {
    ModelC
    FiledA string
}

type ModelB struct {
    ModelC
    FiledB string
}

type ModelC struct {
    Guid string `orm:"pk"`
}

func (this ModelC) Save() error {
    o := orm.NewOrm()
    guid := guidlib.Generate()
    this.Guid = guid
    _, err := o.Insert(this)
    return err
}

但请注意,o.Insert(this)不会插入ModelC未定义的任何字段。正如我在下面的评论中提到的那样,在模型A和B重新实现Save之前可能会使用的继承结构类型在前面调用基类方法并不能很好地在Go中运行。

使用嵌入式类型解决方法的规则并不完全清楚,可能会造成混淆。您可以在嵌入式结构中定义一个Save版本,在嵌入器中重新定义它,甚至可以在该方法中调用它,但它确实没有多大意义。如果您仍然需要静态引用嵌入式类型,我会强调避免嵌入。例如,如果我ModelA嵌入ModelC,并且在更广泛的范围内,我必须ModelA.ModelC.SomeMethodThatIhaveToReferencExplicitlyToEnsureItsCalled(),那么我可能很难使用该功能。

答案 1 :(得分:0)

不,你不能这样做因为golang不支持继承。但你可以做这样的事情:

func Save(obj interface{}) error {
    o := orm.NewOrm()
    guid := guidlib.Generate()
    r := reflect.ValueOf(obj)
    f := reflect.Indirect(r).FieldByName("Guid") 
    f.setString(guid)  
    _, err := o.Insert(obj)
    return err
}

小心,如果没有字段“guid”,它会感到恐慌