Heim  >  Artikel  >  Backend-Entwicklung  >  Reduzieren Sie die Menge an doppeltem Code beim Zuordnen von DTOs in Go

Reduzieren Sie die Menge an doppeltem Code beim Zuordnen von DTOs in Go

WBOY
WBOYnach vorne
2024-02-06 09:00:05536Durchsuche

在 Go 中映射 DTO 时减少重复代码的数量

Frageninhalt

Ich lerne gerade Go und würde mich über die Erkenntnisse der Leute freuen, wie man die Menge an doppeltem Code am besten reduzieren kann.

Die Ordnerstruktur der relevanten Teile ist wie folgt:

.
├── http
│   ├── handlers
│   └── routes
├── models
│   └── dto
├── specifications
└── store
    └── postgres

In meinem specations-Ordner habe ich 2 „Speicher“-Schnittstellen:

type TaskStore interface {
    CreateTask(ctx context.Context, input dto.TaskCreate) error
    UpdateTask(ctx context.Context, id int, input dto.TaskUpdate) error
    GetTask(ctx context.Context, id int) (dto.TaskResult, error)
    ListTasks(ctx context.Context) ([]dto.TaskResult, error)
    DeleteTask(ctx context.Context, id int) error
}

type TagStore interface {
    CreateTag(ctx context.Context, input dto.TagCreate) error
    RenameTag(ctx context.Context, id int, input dto.TagUpdate) error
    ListTags(ctx context.Context) ([]dto.TagResult, error)
    GetTag(ctx context.Context, id int) (dto.TagResult, error)
    DeleteTag(ctx context.Context, id int) error
}
Der Ordner

store/postgres enthält die Implementierung von Aufgaben und Tags (Repository-Muster).

Fragen, die ich sehe:

In meinem handlers-Ordner habe ich eine Struktur, die Eingaben von einer der Speicherschnittstellen entgegennimmt:

type TaskHandler struct {
    store specifications.TaskStore
}

func NewTaskHandler(store specifications.TaskStore) TaskHandler {
    return TaskHandler{
        store: store,
    }
}
type TagHandler struct {
    store specifications.TagStore
}

func NewTagHandler(store specifications.TagStore) TagHandler {
    return TagHandler{
        store: store,
    }
}

Diese Handler enthalten Methoden, die API-Pfaden zugeordnet werden:

func (h TaskHandler) List() http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        tasks, err := h.store.ListTasks(r.Context())
        if err != nil {
            log.Err(err).Msg("failed to retrieve tasks")
            w.WriteHeader(http.StatusInternalServerError)
            return
        }
        render.JSON(w, r, tasks)
    }
}
func (h TagHandler) List() http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        tags, err := h.store.ListTags(r.Context())
        if err != nil {
            log.Err(err).Msg("failed to retrieve tags")
            w.WriteHeader(http.StatusInternalServerError)
            return
        }
        render.JSON(w, r, tags)
    }
}

Sie werden feststellen, dass die List Methoden auf jedem Handler grundsätzlich gleich sind, mit Ausnahme der Schnittstelle, die von jedem Geschäft verwendet wird.

Wie ändere ich diese Einstellung, um doppelten Code zu reduzieren?

Ich dachte zunächst, ich könnte Generika verwenden, um dieses Problem zu lösen, zum Beispiel:

type EntityStore[CreateDto any, UpdateDto any, ResultDto any] interface {
    Create(ctx context.Context, input CreateDto) error
    Update(ctx context.Context, id int, input UpdateDto) error
    List(ctx context.Context) ([]ResultDto, error)
    Get(ctx context.Context, id int) (ResultDto, error)
    Delete(ctx context.Context, id int) error
}

Aber das bedeutet, jeden Typ einem Handler zuzuordnen, was meiner Meinung nach keine praktische Lösung ist.

Irgendwelche Vorschläge, wie ich meine DTOs und Schnittstellen besser abbilden kann?


Richtige Antwort


Sie können eine Hilfsfunktion haben

func ListHandler[T any](name string, lister func(ctx context.Context) ([]T, error)) func(w http.ResponseWriter, r *http.Request) {
    return func(w http.ResponseWriter, r *http.Request) {
        list, err := lister(r.Context())
        if err != nil {
            log.Err(err).Msg("failed to retrieve " + name)
            w.WriteHeader(http.StatusInternalServerError)
            return
        }
        render.JSON(w, r, list)
    }
}

Dann wirst du

haben
func (h TaskHandler) List() http.HandlerFunc {
    return ListHandler("tasks", h.store.ListTasks)
}

func (h TagHandler) List() http.HandlerFunc {
    return ListHandler("tags", h.store.ListTags)
}

Das obige ist der detaillierte Inhalt vonReduzieren Sie die Menge an doppeltem Code beim Zuordnen von DTOs in Go. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen