Skip to content

Setting: extend

extend [PACKAGE:]FUNC... can be defined as CLI argument or conversion comment.

If a type cannot be converted automatically, you can manually define an implementation with :extend for the missing mapping. Keep in mind, Goverter will use the custom implementation every time, when the source and target type matches.

The FUNC may have the signatures described in Signature: Optional Source.

You can optionally define the PACKAGE where FUNC is located by separating the PACKAGE and FUNC with a :(colon). If no package is defined, then the package of the conversion method is used.

TYPE can be a regex if you want to include multiple methods from the same package. E.g. extend IntTo.*.

Here are some examples using extend.

Simple (click to expand)
go
package example

import "fmt"

// goverter:converter
// goverter:extend IntToString
type Converter interface {
	Convert(Input) Output
}
type Input struct {
	Name string
	Age  int
}
type Output struct {
	Name string
	Age  string
}

func IntToString(i int) string {
	return fmt.Sprint(i)
}
go
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter

package generated

import extendlocal "github.com/jmattheis/goverter/example/extend-local"

type ConverterImpl struct{}

func (c *ConverterImpl) Convert(source extendlocal.Input) extendlocal.Output {
	var exampleOutput extendlocal.Output
	exampleOutput.Name = source.Name
	exampleOutput.Age = extendlocal.IntToString(source.Age)
	return exampleOutput
}
Complex (click to expand)
go
package example

// goverter:converter
// goverter:extend ExtractFriendNames
type Converter interface {
	Convert(source []InputPerson) []OutputPerson
}

type InputPerson struct {
	Name    string
	Friends []InputPerson
}
type OutputPerson struct {
	Name    string
	Friends []string
}

func ExtractFriendNames(persons []InputPerson) []string {
	var names []string
	for _, person := range persons {
		names = append(names, person.Name)
	}
	return names
}
go
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter

package generated

import extendlocalcomplex "github.com/jmattheis/goverter/example/extend-local-complex"

type ConverterImpl struct{}

func (c *ConverterImpl) Convert(source []extendlocalcomplex.InputPerson) []extendlocalcomplex.OutputPerson {
	var exampleOutputPersonList []extendlocalcomplex.OutputPerson
	if source != nil {
		exampleOutputPersonList = make([]extendlocalcomplex.OutputPerson, len(source))
		for i := 0; i < len(source); i++ {
			exampleOutputPersonList[i] = c.exampleInputPersonToExampleOutputPerson(source[i])
		}
	}
	return exampleOutputPersonList
}
func (c *ConverterImpl) exampleInputPersonToExampleOutputPerson(source extendlocalcomplex.InputPerson) extendlocalcomplex.OutputPerson {
	var exampleOutputPerson extendlocalcomplex.OutputPerson
	exampleOutputPerson.Name = source.Name
	exampleOutputPerson.Friends = extendlocalcomplex.ExtractFriendNames(source.Friends)
	return exampleOutputPerson
}
With PACKAGE (click to expand)
go
package example

// goverter:converter
// goverter:extend strconv:Atoi
type Converter interface {
	Convert(Input) (Output, error)
}

type Input struct{ Value string }
type Output struct{ Value int }
go
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter

package generated

import (
	extendexternal "github.com/jmattheis/goverter/example/extend-external"
	"strconv"
)

type ConverterImpl struct{}

func (c *ConverterImpl) Convert(source extendexternal.Input) (extendexternal.Output, error) {
	var exampleOutput extendexternal.Output
	xint, err := strconv.Atoi(source.Value)
	if err != nil {
		return exampleOutput, err
	}
	exampleOutput.Value = xint
	return exampleOutput, nil
}
With Conversion interface (click to expand)
go
package example

// goverter:converter
// goverter:extend ConvertAnimals
type Converter interface {
	Convert(source Input) Output

	// used only in extend method
	ConvertDogs([]Dog) []Animal
	ConvertCats([]Cat) []Animal
}

type Input struct {
	Animals InputAnimals
}
type InputAnimals struct {
	Cats []Cat
	Dogs []Dog
}
type Output struct {
	Animals []Animal
}

type Cat struct{ Name string }
type Dog struct{ Name string }

type Animal struct{ Name string }

func ConvertAnimals(c Converter, input InputAnimals) []Animal {
	dogs := c.ConvertDogs(input.Dogs)
	cats := c.ConvertCats(input.Cats)
	return append(dogs, cats...)
}
go
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter

package generated

import extendlocalwithconverter "github.com/jmattheis/goverter/example/extend-local-with-converter"

type ConverterImpl struct{}

func (c *ConverterImpl) Convert(source extendlocalwithconverter.Input) extendlocalwithconverter.Output {
	var exampleOutput extendlocalwithconverter.Output
	exampleOutput.Animals = extendlocalwithconverter.ConvertAnimals(c, source.Animals)
	return exampleOutput
}
func (c *ConverterImpl) ConvertCats(source []extendlocalwithconverter.Cat) []extendlocalwithconverter.Animal {
	var exampleAnimalList []extendlocalwithconverter.Animal
	if source != nil {
		exampleAnimalList = make([]extendlocalwithconverter.Animal, len(source))
		for i := 0; i < len(source); i++ {
			exampleAnimalList[i] = c.exampleCatToExampleAnimal(source[i])
		}
	}
	return exampleAnimalList
}
func (c *ConverterImpl) ConvertDogs(source []extendlocalwithconverter.Dog) []extendlocalwithconverter.Animal {
	var exampleAnimalList []extendlocalwithconverter.Animal
	if source != nil {
		exampleAnimalList = make([]extendlocalwithconverter.Animal, len(source))
		for i := 0; i < len(source); i++ {
			exampleAnimalList[i] = c.exampleDogToExampleAnimal(source[i])
		}
	}
	return exampleAnimalList
}
func (c *ConverterImpl) exampleCatToExampleAnimal(source extendlocalwithconverter.Cat) extendlocalwithconverter.Animal {
	var exampleAnimal extendlocalwithconverter.Animal
	exampleAnimal.Name = source.Name
	return exampleAnimal
}
func (c *ConverterImpl) exampleDogToExampleAnimal(source extendlocalwithconverter.Dog) extendlocalwithconverter.Animal {
	var exampleAnimal extendlocalwithconverter.Animal
	exampleAnimal.Name = source.Name
	return exampleAnimal
}
With context (click to expand)
go
package example

import "time"

// goverter:converter
// goverter:extend FormatTime
type Converter interface {
	// goverter:context dateFormat
	Convert(source map[string]Input, dateFormat string) map[string]Output
}

// goverter:context dateFormat
func FormatTime(t time.Time, dateFormat string) string {
	return t.Format(dateFormat)
}

type Input struct {
	Name      string
	CreatedAt time.Time
}
type Output struct {
	Name      string
	CreatedAt string
}
go
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter

package generated

import dateformat "github.com/jmattheis/goverter/example/context/date-format"

type ConverterImpl struct{}

func (c *ConverterImpl) Convert(source map[string]dateformat.Input, context string) map[string]dateformat.Output {
	var mapStringExampleOutput map[string]dateformat.Output
	if source != nil {
		mapStringExampleOutput = make(map[string]dateformat.Output, len(source))
		for key, value := range source {
			mapStringExampleOutput[key] = c.exampleInputToExampleOutput(value, context)
		}
	}
	return mapStringExampleOutput
}
func (c *ConverterImpl) exampleInputToExampleOutput(source dateformat.Input, context string) dateformat.Output {
	var exampleOutput dateformat.Output
	exampleOutput.Name = source.Name
	exampleOutput.CreatedAt = dateformat.FormatTime(source.CreatedAt, context)
	return exampleOutput
}
With error (click to expand)
go
package example

import "strconv"

// goverter:converter
// goverter:extend StringToInt
type Converter interface {
	Convert(Input) (Output, error)
}

type Input struct{ Value string }
type Output struct{ Value int }

func StringToInt(value string) (int, error) {
	i, err := strconv.Atoi(value)
	return i, err
}
go
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter

package generated

import extendwitherror "github.com/jmattheis/goverter/example/extend-with-error"

type ConverterImpl struct{}

func (c *ConverterImpl) Convert(source extendwitherror.Input) (extendwitherror.Output, error) {
	var exampleOutput extendwitherror.Output
	xint, err := extendwitherror.StringToInt(source.Value)
	if err != nil {
		return exampleOutput, err
	}
	exampleOutput.Value = xint
	return exampleOutput, nil
}