Add Options to prioritize some set of options over another

Added API:
	Default() Option
	FilterPriority(opts ...Option) Option

FilterPriority returns a new Option where an option, opts[i],
is only evaluated if no fundamental options remain after applying all filters
in all prior options, opts[:i].

In order to prevent further options from being evaluated, the Default option
can be used to ensure that some fundamental option remains.

Suppose you have a value tree T, where T1 and T2 are sub-trees within T.
Prior to the addition of FilterPriority, it was impossible to do certain things.

Example 1: You could not make the following compose together nicely.
	* Have a set of options OT1 to affect only values under T1.
	* Have a set of options OT2 to affect only values under T2.
	* Have a set of options OT to affect only T, but not values under T1 and T2.
	* Have a set of options O to affect all other values, but no those in T
	  (and by extension those in T1 and T2).
Solution 1:
	FilterPriority(
		// Since T1 and T2 do not overlap, they could be placed within the
		// same priority level by grouping them in an Options group.
		FilterTree(T1, OT1),
		FilterTree(T2, OT2),
		FilterTree(T, OT),
		O,
	)

Example 2: You could not make the following compose together nicely.
	* Have a set of options O apply on all nodes except those in T1 and T2.
	* Instead, we want the default behavior of cmp on T1 and T2.
Solution 2:
	FilterPriority(
		// Here we show how to group T1 and T2 together to be on the same
		// priority level.
		Options{
			FilterTree(T1, Default()),
			FilterTree(T2, Default()),
		},
		O,
	)

Example 3: You have this: type MyStruct struct { *pb.MyMessage; ... }
	* Generally, you want to use Comparer(proto.Equal) to ensure
	  that all proto.Messages within the struct are properly compared.
	  However, this type has an embedded proto (generally a bad idea),
	  which causes the MyStruct to satisfy the proto.Message interface
	  and unintentionally causes Equal to use proto.Equal on MyStruct,
	  which crashes.
	* How can you have Comparer(proto.Equal) apply to all other
	  proto.Message without applying just to MyStruct?
Solution 3:
	FilterPriority(
		// Only for MyStruct, use the default behavior of Equal,
		// which is to recurse into the structure of MyStruct.
		FilterPath(func(p Path) bool {
			return p.Last().Type() == reflect.TypeOf(MyStruct{})
		}, Default()),

		// Use proto.Equal for all other cases of proto.Message.
		Comparer(proto.Equal),
	)
2 files changed
tree: e56bdb4b6f2a2225d582f24ae9ad3f141fa94191
  1. cmp/
  2. .travis.yml
  3. CONTRIBUTING.md
  4. LICENSE
  5. README.md
README.md

Package for equality of Go values

GoDoc Build Status

This package is intended to be a more powerful and safer alternative to reflect.DeepEqual for comparing whether two values are semantically equal.

The primary features of cmp are:

  • When the default behavior of equality does not suit the needs of the test, custom equality functions can override the equality operation. For example, an equality function may report floats as equal so long as they are within some tolerance of each other.

  • Types that have an Equal method may use that method to determine equality. This allows package authors to determine the equality operation for the types that they define.

  • If no custom equality functions are used and no Equal method is defined, equality is determined by recursively comparing the primitive kinds on both values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, unexported fields are not compared by default; they result in panics unless suppressed by using an Ignore option (see cmpopts.IgnoreUnexported) or explictly compared using the AllowUnexported option.

See the GoDoc documentation for more information.

This is not an official Google product.

Install

go get -u github.com/google/go-cmp/cmp

License

BSD - See LICENSE file