Skip to content

Valuer interface#191

Open
System-Glitch wants to merge 2 commits intojinzhu:masterfrom
System-Glitch:feature/valuer-interface
Open

Valuer interface#191
System-Glitch wants to merge 2 commits intojinzhu:masterfrom
System-Glitch:feature/valuer-interface

Conversation

@System-Glitch
Copy link
Copy Markdown

@System-Glitch System-Glitch commented Aug 10, 2023

This PR adds support for a new copier.Valuer interface. This interface lets custom types implement a function returning the actual value to copy.

For example if your type is a wrapper, or if it doesn't have to implement sql/driver.Valuer, you can implement this interface so the returned value will be used instead. It can also be used to format your type or convert it to another one before being copied.
It differs from TypeConverter in several ways:

  • It can work with generics (see example use-case below). With TypeConverter, you would have to define a type pair for every different generic type you are going to use. This is inconvenient.
  • You don't know the destination type, and you don't need to.
  • It can be used in addition to TypeConverter, where TypeConverter handles the concrete simple types and Valuer allows more complex types to be handled gracefully.

It works in a very simple way: at the start of copier() and set() functions, if the from value implements Valuer,it is replaced with the one returned by CopyValue(), and the usual process continues.

Example use-case:

The Undefined type allows to know if a field in a structure is undefined (which is different from nil, in the case of nullable values). This is useful for PATCH updates so we just omit the fields that are not present.

type Undefined[T any] struct {
	Val     T
	Present bool
}

func (u Undefined[T]) CopyValue() any {
	if !u.Present {
		return nil
	}

	if valuer, ok := any(&u.Val).(copier.Valuer); ok {
		return valuer.CopyValue()
	}
	return u.Val
}

If the field is not present, the struct has its zero-value, which is handy so it can be ignored with the option IgnoreEmpty.


  • Tests
  • Documentation

@System-Glitch
Copy link
Copy Markdown
Author

For those wanting this feature, I decided to maintain a fork: https://github.com/go-goyave/copier

Contributions are also welcome there.

It also includes a few other bug fixes, including #182 #185

Comment thread copier.go
}

func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: unnecessary break line

Comment thread copier_test.go
}

func TestCopyValuer(t *testing.T) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: unnecessary break line

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants