Skip to content

KARTIKrocks/gomapper

Repository files navigation

gomapper

Code generation tool that parses Go struct definitions and generates type-safe mapping functions. Zero reflection, zero runtime cost. In func mode (default), the generated code has zero dependencies.

Go Reference CI Go Report Card Go Version License GitHub tag

Install

go install github.com/KARTIKrocks/gomapper@latest

Usage

Add a go:generate directive to your Go file:

//go:generate gomapper -src User -dst UserDTO

Then run:

go generate ./...

This produces a mapper_gen.go file with pure mapping functions — no runtime dependencies.

Multiple Pairs

//go:generate gomapper -pairs User:UserDTO,Order:OrderDTO

Flags

Flag Default Description
-src Source type name
-dst Destination type name
-pairs Comma-separated Src:Dst pairs
-output mapper_gen.go Output file name
-mode func func (pure functions), register, or both
-bidirectional false Generate both S→D and D→S mappings
-tag map Struct tag key for field renaming
-strict false Fail if any destination field is unmapped
-ci false Case-insensitive field name matching
-nil-safe false Generate nil checks for pointer dereferences
-v false Verbose output

Modes

  • func (default) — generates pure MapSrcToDst functions. No imports, no reflection, compile-time type safety. Slice fields produce inline loops.
  • register — generates mapper.Register(...) calls for the mapper library's runtime registry.
  • both — generates named functions and registers them via mapper.Register.

Field Matching

Fields are matched in this order:

  1. Fields with map:"-" tag are skipped entirely (on either source or destination)
  2. Destination field map:"SourcePath" tag (supports dot notation for nested structs)
  3. Source field map:"DstName" tag
  4. Exact name match with assignable type → direct assignment
  5. Exact name match with convertible type → type conversion
  6. Case-insensitive name match (with -ci flag) — UserName matches Username
  7. Pointer handling: *TT (dereference), T*T (address-of), *TU (deref + convert)
  8. Nested struct mapping: AddressAddressDTO generates MapAddressToAddressDTO(src.Addr) (func/both) or mapper.Map[AddressDTO](src.Addr) (register)
  9. Slice handling: []T[]U generates inline loop calling MapTToU (func/both) or mapper.MapSlice (register)
  10. No match → // TODO: unmapped field comment (or error in -strict mode)

Unexported fields are skipped. Embedded struct promoted fields are included.

Example

Input:

type User struct {
    ID    int
    Name  string
    Email string
}

type UserDTO struct {
    ID   int
    Name string
}

Generated (mapper_gen.go):

// Code generated by gomapper; DO NOT EDIT.

package mypackage

func MapUserToUserDTO(src User) UserDTO {
    return UserDTO{
        ID:   src.ID,
        Name: src.Name,
    }
}

No imports. No reflection. Just a function.

Case-Insensitive Matching

Use -ci when source and destination fields differ only by casing:

type CISrc struct { UserName string; EMail string }
type CIDst struct { Username string; Email string }
gomapper -src CISrc -dst CIDst -ci

Exact matches always take priority — -ci is only a fallback.

Nested Struct Mapping

When both source and destination fields are different named struct types, gomapper generates a call to the corresponding mapping function:

type Address    struct { Street, City string }
type AddressDTO struct { Street, City string }
type Order      struct { ID int; Addr Address }
type OrderDTO   struct { ID int; Addr AddressDTO }
gomapper -pairs Address:AddressDTO,Order:OrderDTO

Generated:

func MapOrderToOrderDTO(src Order) OrderDTO {
    return OrderDTO{
        ID:   src.ID,
        Addr: MapAddressToAddressDTO(src.Addr),
    }
}

In register mode, nested struct fields use mapper.Map[AddressDTO](src.Addr) instead.

Nil-Safe Pointer Dereference

By default, pointer-to-value mappings generate bare dereferences (*src.Name) which panic on nil. Use -nil-safe to generate nil checks:

type PtrSrc struct { Name *string; Age *int }
type PtrDst struct { Name string;  Age int64 }
gomapper -src PtrSrc -dst PtrDst -nil-safe

Generated:

func MapPtrSrcToPtrDst(src PtrSrc) PtrDst {
    var _Name string
    if src.Name != nil {
        _Name = *src.Name
    }
    var _Age int64
    if src.Age != nil {
        _Age = int64(*src.Age)
    }
    return PtrDst{
        Name: _Name,
        Age:  _Age,
    }
}

Without -nil-safe, pointer fields use the original *src.Name / int64(*src.Age) expressions.

Known Limitations

  • Multi-level pointers (**T, ***T) are not dereferenced — only single-level *TT is handled. Fields with deeper pointer indirection will appear as // TODO: unmapped.

About

A Go code generator that produces type-safe, zero-reflection struct mapping functions from simple //go:generate directives.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors