1

In go v1.19.2, I'm hoping to be able to use generics to delete objects in a database using gorm. The roadblock I'm finding is that I can't seem to be able to create a new object based on a given generic type and then populate the Id value in order to pass that value to the orm's Delete() function.

Below is my sample code that fails to compile. I've implemented 4 different ways trying to update the Id of the newly created generic-passed type, but all variations give me compiler errors. Each compiler error is noted in the code.

package main

// based on: https://stackoverflow.com/a/33642734/5572674
type ModelA struct {
    ModelC
    FiledA string
}

type ModelB struct {
    ModelC
    FiledB string
}

type ModelC struct {
    Id int `orm:"pk"`
}

type IModelC interface {
    setId(id int)
}

func (m *ModelC) setIdViaPtr(id int) {
    m.Id = id
}

func (m *ModelC) setId(id int) {
    m.Id = id
}

// mock of orm.Delete
func Delete(md interface{}, cols ...string) (int64, error) {
    return 0, nil
}

func DeleteGenericById[T ModelC](id int) error {
    tPtr := new(T)
    // 4 diferent attempts ... all fail with compiler errors
    tPtr.setIdViaPtr(id)       //COMPILE ERROR: tPtr.setIdViaPtr undefined (type *T is pointer to type parameter, not type parameter)
    (*tPtr).setIdViaPtr(id)    //COMPILE ERROR: (*tPtr).setIdViaPtr undefined (type T has no field or method setIdViaPtr)
    (*tPtr).setId(id)          // COMPILE ERROR: (*tPtr).setId undefined (type T has no field or method setId)
    (*ModelC)(*tPtr).setId(id) // COMPILE ERROR: cannot convert *tPtr (variable of type T constrained by ModelC) to *ModelC (cannot convert ModelC (in T) to *ModelC
    _, err := Delete(tPtr)
    return err
}

I implemented code in 4 different ways in order to update the generic type Id but all resulted in compile errors noted in comments in the code.

blackgreen
  • 34,072
  • 23
  • 111
  • 129
RJLyders
  • 353
  • 3
  • 9
  • Your type param is constrained by `ModelC` which is a struct. This doesn’t make sense because you could just as well do `tPtr := &ModelC{}`. Start by replacing that with the interface `IModelC`, then perhaps update your question – blackgreen Nov 12 '22 at 17:34
  • Thanks @blackgreen I've updated my question with my final solution. – RJLyders Nov 13 '22 at 05:24
  • It's great that you could figure this out, and understand why it was marked as a duplicate. On SO usually it's better to not post solutions inside questions, because it can get confusing. If you want to be helpful to others, please post the solution under one of the open questions that helped you resolve the issue (make sure it addresses the question). Also please don't delete this question, even if it's closed it is useful because it points to the solutions. – blackgreen Nov 16 '22 at 16:19

0 Answers0