As a firm believer, I strongly emphasize things with separation of concerns. If you look into countless go repositories, you will see unstructured models with no aim to distinguish between request and response models.
Further way things get more bizarre and I see entities(database models) dumped into a single model package where every request, response models exist. I have seen countless times people are super lazy to create separate entity - DTO(data transfer object) structs
then they end up with exposing entity struct to end user via REST API including relational database IDs. This is generally due to laziness of creating a new struct which could be response struct with omitted fields.
I can not blame the laziness sometimes if you have a thousand of properties, it is actually really annoying to map something from request to your database model then your database model to response. This is where I thought I need a powerful yet so simple mapper codegen for too many fields
- 1-to-1 struct-struct mapping
- Maps underlying nested slices, maps, structs
- Maps same types with same variable names by default
- Maps same types with different names by tag specification in source struct
- Does use reflection to generate mapperx package at compile time
- Doesn't aim to do aggregation while mapping
- Doesn't map not equal types
- Doesn't use reflection at runtime
Mapperx heavily relies on code generation. This means that you need to specify 3 flag arguments source(file path and struct type) and target(file path and struct type) and output(output directory) Then mapperx will generate a directory and a package called mapperx, when you run it. The Easiest way to use is to do go generate compiler directive in your definitions at the start of a file.
go get -u github.com/MrWormHole/mapperx
package main
//go:generate go run github.com/MrWormHole/mapperx -source=github.com/MrWormHole/mapperx/examples/model.Admin -target=github.com/MrWormHole/mapperx/examples/model.User -directory=../mapperx -filename=XXX_ADMIN_TO_USER_XXX
// OR
///go:generate go run github.com/MrWormHole/mapperx -source=github.com/MrWormHole/mapperx/examples/model.Admin -target=github.com/MrWormHole/mapperx/examples/model.User
type troll bool
type Admin struct {
Name string
ID string
Country string
Score string `mapperx:"Highscore"`
troll troll
Friends []string
Permissions map[string]string `mapperx:"GivenPermissions"`
Minion *Minion
}
type User struct {
Name string
ID string
Country string
Highscore string
troll troll
Friends []string
GivenPermissions map[string]string
Minion *Minion
}
Output file will look something like this
// Code generated by mapperx, PLEASE DO NOT EVER EDIT. GENERATATED AT 2021-06-22 10:14:21.5543809 +0100 BST m=+0.393255201
package mapperx
import model "github.com/MrWormHole/mapperx/examples/model"
func AdminToUser(admin *model.Admin, user *model.User) {
user.Name = admin.Name
user.ID = admin.ID
user.Country = admin.Country
user.Highscore = admin.Score
user.Friends = make([]string, len(admin.Friends))
copy(user.Friends, admin.Friends)
user.GivenPermissions = make(map[string]string, len(admin.Permissions))
for k, v := range admin.Permissions {
user.GivenPermissions[k] = v
}
user.Minion = admin.Minion
}