Setting: extend
extend [PACKAGE:]TYPE...
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.
See signatures for possible method signatures.
extend TYPE
extend TYPE
allows you to reference a method in the local package. E.g:
TYPE
can be a regex if you want to include multiple methods from the same package. E.g. extend IntTo.*
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)
}
// 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 example (click to expand)
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
}
// 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
}
extend PACKAGE:TYPE
You can extend methods from external packages by separating the package path with :
from the method.
TYPE
can be a regex if you want to include multiple methods from the same package. E.g. extend strconv:A.*
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 }
// 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
}
Signatures
Method with converter
You can access the generated converter by defining the converter interface as first parameter.
func IntToString(c Converter, i int) string {
// Use c.ConvertSomething()
return fmt.Sprint(i)
}
Example (click to expand)
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...)
}
// 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
}
Method with error
Sometimes, custom conversion may fail, in this case Goverter allows you to define a second return parameter which must of type error
func IntToString(i int) (string, error) {
return "42", errors.new("oops something went wrong")
}
Example (click to expand)
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
}
// 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
}