diff --git a/cmp/cmpopts/ignore.go b/cmp/cmpopts/ignore.go index e86554b..6d9b514 100644 --- a/cmp/cmpopts/ignore.go +++ b/cmp/cmpopts/ignore.go @@ -112,6 +112,10 @@ func (tf ifaceFilter) filter(p cmp.Path) bool { // In particular, unexported fields within the struct's exported fields // of struct types, including anonymous fields, will not be ignored unless the // type of the field itself is also passed to IgnoreUnexported. +// +// Avoid ignoring unexported fields of a type which you do not control (i.e. a +// type from another repository), as changes to the implementation of such types +// may change how the comparison behaves. Prefer a custom Comparer instead. func IgnoreUnexported(typs ...interface{}) cmp.Option { ux := newUnexportedFilter(typs...) return cmp.FilterPath(ux.filter, cmp.Ignore()) diff --git a/cmp/options.go b/cmp/options.go index 6d4335b..a265597 100644 --- a/cmp/options.go +++ b/cmp/options.go @@ -225,7 +225,7 @@ func (validator) apply(s *state, vx, vy reflect.Value) { // Unable to Interface implies unexported field without visibility access. if !vx.CanInterface() || !vy.CanInterface() { - const help = "consider using AllowUnexported or cmpopts.IgnoreUnexported" + const help = "consider using a custom Comparer; if you control the implementation of type, you can also consider AllowUnexported or cmpopts.IgnoreUnexported" panic(fmt.Sprintf("cannot handle unexported field: %#v\n%s", s.curPath, help)) } @@ -371,7 +371,7 @@ func (cm comparer) String() string { // defined in an internal package where the semantic meaning of an unexported // field is in the control of the user. // -// For some cases, a custom Comparer should be used instead that defines +// In many cases, a custom Comparer should be used instead that defines // equality as a function of the public API of a type rather than the underlying // unexported implementation. //