Skip to content

How to pass context to custom functions

You can pass additional parameters to custom functions by defining them as context. This can be done by prefixing the parameter names with context or ctx. Use this guide to get a broad overview on how to use this feature.

If we want to format a time.Time to string but have requirements so that the date format must be changeable at runtime. You can define the time format as context, and then use it in a custom extend function.

go
package example

import "time"

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

func FormatTime(t time.Time, ctxFormat string) string {
	return t.Format(ctxFormat)
}

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
}

Similarly, you could supply a database handle and query additional values that are needed in the target but missing in the source. E.g. in this example if a specific post is editable:

go
package example

// goverter:converter
type Converter interface {
	// goverter:map ID Editable | QueryEditable
	Convert(source PostInput, ctxDatabase Database) (PostOutput, error)
}

func QueryEditable(id int, ctxDatabase Database) bool {
	return ctxDatabase.AllowedToEdit(id)
}

type Database interface {
	AllowedToEdit(id int) bool
}

type PostInput struct {
	ID   int
	Body string
}
type PostOutput struct {
	ID       int
	Body     string
	Editable bool
}
go
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter

package generated

import database "github.com/jmattheis/goverter/example/context/database"

type ConverterImpl struct{}

func (c *ConverterImpl) Convert(source database.PostInput, context database.Database) (database.PostOutput, error) {
	var examplePostOutput database.PostOutput
	examplePostOutput.ID = source.ID
	examplePostOutput.Body = source.Body
	examplePostOutput.Editable = database.QueryEditable(source.ID, context)
	return examplePostOutput, nil
}