search
HomeBackend DevelopmentGolangReduce the amount of duplicate code when mapping DTOs in Go

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

Question content

I'm currently learning Go and would appreciate people's insights on how best to reduce the amount of duplicate code.

The folder structure of the relevant parts is as follows:

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

In my specations folder I have 2 "storage" interfaces:

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
}
The

store/postgres folder contains the implementation of tasks and tags (repository mode).

Questions I saw:

In my handlers folder I have a struct that accepts input from one of the storage interfaces:

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,
    }
}

These handlers contain methods that will be mapped to api paths:

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)
    }
}

You'll notice that the List methods on each handler are basically the same, except for the interface used by each store.

How can I change this setting to reduce duplicate code?

I initially thought I could use generics to solve this problem, for example:

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
}

But this means mapping each type into a handler, which I don't think is a practical solution.

Any suggestions on how to better map my DTOs and interfaces?


Correct answer


You can have a helper function

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)
    }
}

Then you will have

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

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

The above is the detailed content of Reduce the amount of duplicate code when mapping DTOs in Go. For more information, please follow other related articles on the PHP Chinese website!

Statement
This article is reproduced at:stackoverflow. If there is any infringement, please contact admin@php.cn delete
init Functions and Side Effects: Balancing Initialization with Maintainabilityinit Functions and Side Effects: Balancing Initialization with MaintainabilityApr 26, 2025 am 12:23 AM

Toensureinitfunctionsareeffectiveandmaintainable:1)Minimizesideeffectsbyreturningvaluesinsteadofmodifyingglobalstate,2)Ensureidempotencytohandlemultiplecallssafely,and3)Breakdowncomplexinitializationintosmaller,focusedfunctionstoenhancemodularityandm

Getting Started with Go: A Beginner's GuideGetting Started with Go: A Beginner's GuideApr 26, 2025 am 12:21 AM

Goisidealforbeginnersandsuitableforcloudandnetworkservicesduetoitssimplicity,efficiency,andconcurrencyfeatures.1)InstallGofromtheofficialwebsiteandverifywith'goversion'.2)Createandrunyourfirstprogramwith'gorunhello.go'.3)Exploreconcurrencyusinggorout

Go Concurrency Patterns: Best Practices for DevelopersGo Concurrency Patterns: Best Practices for DevelopersApr 26, 2025 am 12:20 AM

Developers should follow the following best practices: 1. Carefully manage goroutines to prevent resource leakage; 2. Use channels for synchronization, but avoid overuse; 3. Explicitly handle errors in concurrent programs; 4. Understand GOMAXPROCS to optimize performance. These practices are crucial for efficient and robust software development because they ensure effective management of resources, proper synchronization implementation, proper error handling, and performance optimization, thereby improving software efficiency and maintainability.

Go in Production: Real-World Use Cases and ExamplesGo in Production: Real-World Use Cases and ExamplesApr 26, 2025 am 12:18 AM

Goexcelsinproductionduetoitsperformanceandsimplicity,butrequirescarefulmanagementofscalability,errorhandling,andresources.1)DockerusesGoforefficientcontainermanagementthroughgoroutines.2)UberscalesmicroserviceswithGo,facingchallengesinservicemanageme

Custom Error Types in Go: Providing Detailed Error InformationCustom Error Types in Go: Providing Detailed Error InformationApr 26, 2025 am 12:09 AM

We need to customize the error type because the standard error interface provides limited information, and custom types can add more context and structured information. 1) Custom error types can contain error codes, locations, context data, etc., 2) Improve debugging efficiency and user experience, 3) But attention should be paid to its complexity and maintenance costs.

Building Scalable Systems with the Go Programming LanguageBuilding Scalable Systems with the Go Programming LanguageApr 25, 2025 am 12:19 AM

Goisidealforbuildingscalablesystemsduetoitssimplicity,efficiency,andbuilt-inconcurrencysupport.1)Go'scleansyntaxandminimalisticdesignenhanceproductivityandreduceerrors.2)Itsgoroutinesandchannelsenableefficientconcurrentprogramming,distributingworkloa

Best Practices for Using init Functions Effectively in GoBest Practices for Using init Functions Effectively in GoApr 25, 2025 am 12:18 AM

InitfunctionsinGorunautomaticallybeforemain()andareusefulforsettingupenvironmentsandinitializingvariables.Usethemforsimpletasks,avoidsideeffects,andbecautiouswithtestingandloggingtomaintaincodeclarityandtestability.

The Execution Order of init Functions in Go PackagesThe Execution Order of init Functions in Go PackagesApr 25, 2025 am 12:14 AM

Goinitializespackagesintheordertheyareimported,thenexecutesinitfunctionswithinapackageintheirdefinitionorder,andfilenamesdeterminetheorderacrossmultiplefiles.Thisprocesscanbeinfluencedbydependenciesbetweenpackages,whichmayleadtocomplexinitializations

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function