Как добавить метод для различных структур, которые имеют одно общее поле в golang

Я использую beego/orm для своего приложения. Здесь у меня есть 2 модели

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

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

Мне нужно добавить Save() метод для каждой структуры. В общем, я могу создать Base структурировать и смешать в ModelA а также ModelB, но форма не будет работать.

Есть ли лучшее решение?

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 ответа

Решение

Да. Определить интерфейс. Кроме того, ненавижу придирки, хотя я уверен, что вы говорите о встраивании, в Go нет концепции "смешивания". Вот некоторый псевдокод, демонстрирующий конструкции.

type Savable interface {
       Save()
}

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

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

РЕДАКТИРОВАТЬ: на основе некоторых дискуссий кажется, что ОП, вероятно, хочет сделать что-то вроде ниже

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 во встроенных структурах переопределите его в embedor и даже вызовите его в этом методе, однако делать это не имеет особого смысла. Я бы хотел избежать встраивания, если вам все равно придется статически ссылаться на встроенный тип. Например, если у меня есть ModelA вложения ModelC и в более широком смысле я должен сделать ModelA.ModelC.SomeMethodThatIhaveToReferencExplicitlyToEnsureItsCalled() тогда я, вероятно, плохо использую эту функцию.

Нет, вы не можете сделать это, потому что Голанг не поддерживает наследование. Но вы можете сделать что-то вроде этого:

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"

Другие вопросы по тегам