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

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

问题描述:

I'm using beego/orm for my app. Here I have 2 models

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

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

I need to add a Save() method for each struct. In general, I can create an Base struct and mixin it into ModelA and ModelB, but the orm would not work.

Is there any better solution?

edit1: Giving Save() code here to make question more clear

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
}

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

  type ModelA struct {
 Guid string`orm:“ pk”`
 FiledA string 
} 
 
type ModelB struct {
 引导字符串`orm:“ pk”`
 FiledB字符串
} 
  code>  pre> 
 
 

我需要添加 Save() code>方法 每个结构。 通常,我可以创建一个 Base code>结构并将其混合到 ModelA code>和 ModelB code>中,但是该orm无法正常工作。 p> \ n

是否有更好的解决方案? p>

edit1: strong>:在此处提供 Save() code>代码以使问题更清楚 p>

  func(此* ModelA)Save()错误{
o:= orm.NewOrm()
 guid:= guidlib.Generate()
 this.Guid =  guid 
 _,err:= o。插入(this)
返回err 
} 
 
func(this * ModelB)Save()错误{
o:= orm.NewOrm()
 guid:= guidlib  .Generate()
 this.Guid = guid 
 _,err:= o.Insert(this)
 return err 
} 
  code>  pre> 
  div>

Yes. Define an interface. Also, hate to nitpick, while I'm pretty sure you're talking about embedding there isn't a 'mixin' concept that exists in Go. Here's some pseudo code that demonstrates the constructs.

type Savable interface {
       Save()
}

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

var i Savable
i = SomeMethodThatRetunsMyModel()
i.Save()
SomeOthermMethodThatAcceptsASavableAndCallesSave(i)

EDIT: based on some discussion seems like the OP probably wants to do something like below

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
}

However, note that o.Insert(this) is not going to insert any fields that aren't defined on ModelC. As I mentioned in my comment below the type of inheritance structure that might be used where models A and B would reimplement Save calling the base classes method upfront doesn't really work well in Go.

The rules for method resolution with embedded types aren't completely clear and can be confusing. You could define one version of Save in the embedded structs, redefine it in the embedor and even call it within that method however it doesn't really make much sense to do. I would make a point to avoid embedding if you're still going to have to statically reference the embedded type. For example if I have ModelA embedding ModelC and in the broader scope I'm having to do ModelA.ModelC.SomeMethodThatIhaveToReferencExplicitlyToEnsureItsCalled() then I'm probably making poor use of the feature.

No, you can not do this because golang do not support inherit. But you can do something like this bellow:

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
}

Be careful, it will panic if there is not field "guid"