Automap: Automated mapping generation in Go
THIS PROJECT IS IN PROOF OF CONCEPT STAGE AND IS DEFINITELY
NOT SUITABLE FOR USE IN PRODUCTION
Automap is a code generation tool that automates creation of mappings between
different types. Resulting code operates without any additional runtime or
reflection, so it doesn't incur any runtime overhead compared to handwritten
mappings. Most of problems with generating mappings will happen at compile
time, unlike other automapping solutions based on reflection that tend to fail
at runtime. Finally, generated mappings are susceptible to code analysis tools
and can also be easily navigated manually.
This tool is heavily inspired by:
- Wire:
dependency injection framework for Go based on code generation
- AutoMapper:
convention-based object-object mapper in .NET
Installing
Install AutoMap by running:
go get github.com/skhoroshavin/automap/cmd/automap
and ensuring that $GOPATH/bin
is added to your $PATH
.
Quick start
Suppose you want to create a mapping from type User
to UserDTO
.
To do so first you need to create an automap.go
file in your project with
the following contents:
//go:build automap
package mypackage
import "github.com/skhoroshavin/automap"
func UserToDTO(user *User) *UserDTO {
panic(automap.Build())
}
Note that:
- it starts with build tag
automap
which prevents this file from compiling
during normal build process
- it contains mapper function with desired signature
- implementation of that mapper function is just a stub which panics with the
result of marker function
automap.Build()
Then run automap
tool in same directory which will create automap_gen.go
file with roughly following contents:
// Code generated by automap. DO NOT EDIT.
//go:build !automap
//go:generate automap
package mypackage
func UserToDTO(user *User) *UserDTO {
return &UserDTO{
FirstName: user.FirstName,
LastName: user.LastName,
}
}
Note that:
- it starts with
!automap
build tag, so it doesn't interfere with subsequent
runs of this tool
- it includes
go:generate
statement, so mappings can be updated just with
normal go generate
calls, no need to explicitly run automap
after first
bootstrapping
- it doesn't import anything related to
automap
anymore
- generated mapper has same signature as initial stub, and contains explicit
mapping of fields that have matching names
- if target type has fields that cannot be matched to any of inputs mapping
generation will fail - this will prevent accidentally creating incomplete
mappings
- Making this behaviour configurable (for example by somehow
providing custom mappings for such fields) is planned in future versions.