Documentation
ΒΆ
Overview ΒΆ
Package mapper provides a type-safe, generic mapping library for Go that allows registration and execution of mapping functions between different types. It supports both manual mapping function registration and automatic field mapping.
Package mapper provides automatic mapping functionality using reflection and the jinzhu/copier library
Index ΒΆ
- Variables
- func Has[S any, D any](m Mapper) bool
- func List(m Mapper) []string
- func Map[S any, D any](m Mapper, src S) (D, error)
- func MapSlice[S any, D any](m Mapper, src S) (D, error)
- func Register[S any, D any](m Mapper, fn func(S) D)
- func RegisterAutoMap[S any, D any](m Mapper)
- func Remove[S any, D any](m Mapper)
- type Mapper
Constants ΒΆ
This section is empty.
Variables ΒΆ
var ErrNoMapping = errors.New("no mapping function registered for this type pair")
ErrNoMapping is returned when attempting to map between types that don't have a registered mapping function.
var ErrSrcAndDestMustBeSlices = errors.New("both source and destination must be slices")
ErrSrcAndDestMustBeSlices is returned when a function expects both the source and destination parameters to be slices, but one or both are not. This error helps enforce type safety when performing operations that require slice types.
var Global = New()
Global is a default mapper instance that can be used for convenience. It provides a shared mapping registry for applications that don't need multiple mapper instances.
Functions ΒΆ
func Has ΒΆ added in v0.2.0
Has checks if a mapping function is registered for the specified type pair. This is useful for conditional mapping or validation before attempting to map.
Type Parameters:
- S: Source type to check for mapping
- D: Destination type to check for mapping
Parameters:
- m: The mapper instance to check
Returns:
- bool: true if a mapping function is registered for S -> D, false otherwise
Example:
mapper := New()
Register(mapper, func(s string) int { return len(s) })
if Has[string, int](mapper) {
result, _ := Map[string, int](mapper, "hello")
fmt.Println("Mapped:", result)
} else {
fmt.Println("No mapping available")
}
fmt.Println(Has[int, string](mapper)) // Output: false
func List ΒΆ
List returns a slice of strings representing all registered mapping type pairs. Each string is formatted as "SourceType-DestinationType" and can be used for debugging, logging, or displaying available mappings to users.
Parameters:
- m: The mapper instance to list mappings from
Returns:
- []string: A slice of strings representing all registered type pair mappings
Example:
mapper := New()
Register(mapper, func(s string) int { return len(s) })
Register(mapper, func(i int) string { return fmt.Sprintf("%d", i) })
Register(mapper, func(p Person) PersonDTO { return PersonDTO{Name: p.Name} })
mappings := List(mapper)
for _, mapping := range mappings {
fmt.Println("Available mapping:", mapping)
}
// Output:
// Available mapping: string-int
// Available mapping: int-string
// Available mapping: main.Person-main.PersonDTO
func Map ΒΆ
Map executes a registered mapping function to convert a value from type S to type D. It supports mapping between values, pointers, and mixed value/pointer combinations. The function automatically handles pointer dereferencing and creation as needed.
Type Parameters:
- S: Source type (must match a registered mapping function's input type)
- D: Destination type (must match a registered mapping function's output type)
Parameters:
- m: The mapper instance containing the registered mapping functions
- src: The source value to be mapped
Returns:
- D: The mapped result of type D
- error: ErrNoMapping if no mapping function is registered for the type pair
Supported mapping combinations:
- Value to Value: T -> U
- Pointer to Pointer: *T -> *U (nil input returns nil output)
- Value to Pointer: T -> *U
- Pointer to Value: *T -> U (nil input returns zero value)
Example:
mapper := New()
Register(mapper, func(s string) int { return len(s) })
result, err := Map[string, int](mapper, "hello")
if err != nil {
log.Fatal(err)
}
fmt.Println(result) // Output: 5
// Pointer mapping
name := "world"
ptrResult, err := Map[*string, *int](mapper, &name)
if err != nil {
log.Fatal(err)
}
fmt.Println(*ptrResult) // Output: 5
func MapSlice ΒΆ added in v0.2.0
MapSlice applies a registered mapping function to each element of a slice, returning a new slice with the mapped elements. It supports various combinations of slice element types including values and pointers.
Type Parameters:
- S: Source slice type (e.g., []SourceType, []*SourceType)
- D: Destination slice type (e.g., []DestType, []*DestType)
Parameters:
- m: The mapper instance containing the registered mapping functions
- src: The source slice to be mapped
Returns:
- D: A new slice containing the mapped elements
- error: ErrNoMapping if no mapping function is registered for the element types, or an error if source/destination are not slices
Supported slice mapping combinations:
- []T -> []U: Value elements to value elements
- []*T -> []*U: Pointer elements to pointer elements (nil elements remain nil)
- []T -> []*U: Value elements to pointer elements
- []*T -> []U: Pointer elements to value elements (nil elements become zero values)
Example:
mapper := New()
Register(mapper, func(s string) int { return len(s) })
words := []string{"hello", "world", "go"}
lengths, err := MapSlice[[]string, []int](mapper, words)
if err != nil {
log.Fatal(err)
}
fmt.Println(lengths) // Output: [5 5 2]
// Pointer slice mapping
wordPtrs := []*string{&words[0], nil, &words[2]}
lengthPtrs, err := MapSlice[[]*string, []*int](mapper, wordPtrs)
if err != nil {
log.Fatal(err)
}
// lengthPtrs will be [*5, nil, *2]
func Register ΒΆ
Register registers a mapping function for converting from type S to type D. The function will be stored in the mapper's registry and can be used by Map and MapSlice. If a mapping for the same type pair already exists, it will be overwritten.
Type Parameters:
- S: Source type (input type for the mapping function)
- D: Destination type (output type for the mapping function)
Parameters:
- m: The mapper instance to register the function with
- fn: The mapping function that converts from S to D
Example:
mapper := New()
Register(mapper, func(s string) int { return len(s) })
Register(mapper, func(p Person) PersonDTO {
return PersonDTO{Name: p.FirstName + " " + p.LastName}
})
func RegisterAutoMap ΒΆ
RegisterAutoMap registers bidirectional automatic mapping functions for types S and D. This function creates mapping functions that use reflection to automatically copy matching fields between structs. Both S->D and D->S mappings are registered.
The automatic mapping uses the jinzhu/copier library, which copies fields with matching names and compatible types. This is convenient for mapping between similar structs but comes with a performance cost compared to manually registered functions.
Performance Note: AutoMap functions are approximately 50x slower than manually registered mapping functions (~1600ns vs ~25ns per operation) due to reflection overhead.
Type Parameters:
- S: Source type for bidirectional mapping
- D: Destination type for bidirectional mapping
Parameters:
- m: The mapper instance to register the automatic mapping functions with
Example:
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
type UserDTO struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
mapper := New()
RegisterAutoMap[User, UserDTO](mapper)
user := User{ID: 1, Name: "John", Email: "john@example.com"}
dto, err := Map[User, UserDTO](mapper, user)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Mapped DTO: %+v\n", dto)
// Reverse mapping is also available
backToUser, err := Map[UserDTO, User](mapper, dto)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Mapped back: %+v\n", backToUser)
func Remove ΒΆ added in v0.2.0
Remove unregisters a mapping function for the specified type pair. After removal, attempting to map between these types will return ErrNoMapping. This operation is safe to call even if no mapping exists for the type pair.
Type Parameters:
- S: Source type to remove mapping for
- D: Destination type to remove mapping for
Parameters:
- m: The mapper instance to remove the mapping from
Example:
mapper := New()
Register(mapper, func(s string) int { return len(s) })
fmt.Println(Has[string, int](mapper)) // Output: true
Remove[string, int](mapper)
fmt.Println(Has[string, int](mapper)) // Output: false
_, err := Map[string, int](mapper, "hello")
fmt.Println(err) // Output: no mapping function registered for this type pair
Types ΒΆ
type Mapper ΒΆ
type Mapper struct {
// contains filtered or unexported fields
}
Mapper is the main mapping registry that stores mapping functions between type pairs. Each mapper instance maintains its own independent registry of mapping functions.
func New ΒΆ added in v0.2.0
func New() Mapper
New creates a new Mapper instance with an empty registry. Each mapper maintains its own independent registry of mapping functions.
Returns:
- Mapper: A new mapper instance with an initialized empty registry
Example:
mapper := New()
Register(mapper, func(s string) int { return len(s) })
result, err := Map[string, int](mapper, "hello")