Linked Questions

Popular Questions

I've a generic Repository that could be used for multiple structs (that hopefully extends Model), currently it is defined Repository[M any].

Because M is of type any, I can't access Model's fields without reflection. I couldn't figure out a way of defining something like Repository[M extends Model]. I know that I won't be able to access SomeModel and SomeOtherModel fields without casting/reflection, but those are not relevant at the moment.

I want to keep it generic to leverage retrieval methods, i.e.: FindBy and return the correct typing upstream.

Note: I understand that Go doesn't have inheritance and works via composition, I'm using the word "extends" just as a reference.

Playground: https://go.dev/play/p/Jwk7XxoDu1o
Code:

package main

import "reflect"

type Model struct {
    Id string
    // ... other generic fields
}

// Generic Repository used by multiple models
type Repository[M any] struct {
}

func (r *Repository[M]) FindBy(id string) (*M, error) {
    model := new(M)
    return model, nil
}

func (r *Repository[M]) Update(model M) {
    // HERE: How to access model.Id without reflection?
}

// Multiple "Model" Impl
type SomeModel struct {
    Model
}

type SomeOtherModel struct {
    Model
}

func main() {
    repo1 := &Repository[SomeModel]{}
    someModel, _ := repo1.FindBy("1")
    repo1.Update(*someModel)

    repo2 := &Repository[SomeOtherModel]{}
    someOtherModel, _ := repo2.FindBy("1")
    repo2.Update(*someOtherModel)

    println(reflect.TypeOf(*someModel).Name(), reflect.TypeOf(*someOtherModel).Name())
}

Related Questions