diff --git a/cmp/cmpopts/example_test.go b/cmp/cmpopts/example_test.go index 0d19cb0..b62002f 100644 --- a/cmp/cmpopts/example_test.go +++ b/cmp/cmpopts/example_test.go @@ -53,6 +53,44 @@ func ExampleIgnoreFields_testing() { // } } +// IgnoreUnexported drops unexported fields of the named struct types from the +// comparison entirely. This is useful when comparing types that contain +// unexported state (caches, timestamps, internal bookkeeping) that should not +// affect equality. +// +// Unlike [github.com/google/go-cmp/cmp.AllowUnexported], which allows the +// fields to be compared, IgnoreUnexported skips them. Only the immediate +// unexported fields of the listed types are ignored; unexported fields on +// nested struct types are not ignored unless those types are also listed. +func ExampleIgnoreUnexported() { + // user has an exported Name and an unexported cache field that is not + // part of the user's identity. + type user struct { + Name string + cache string + } + + x := user{Name: "alice", cache: "stale"} + y := user{Name: "alice", cache: "fresh"} + z := user{Name: "bob", cache: "fresh"} + + // IgnoreUnexported drops user.cache from the comparison. + opt := cmpopts.IgnoreUnexported(user{}) + + fmt.Println(cmp.Equal(x, y, opt)) + fmt.Println(cmp.Equal(x, z, opt)) + fmt.Println(cmp.Diff(x, z, opt)) + + // Output: + // true + // false + // cmpopts_test.user{ + // - Name: "alice", + // + Name: "bob", + // ... // 1 ignored field + // } +} + type ( Gateway struct { SSID string diff --git a/cmp/example_test.go b/cmp/example_test.go index 318143b..5821e62 100644 --- a/cmp/example_test.go +++ b/cmp/example_test.go @@ -303,6 +303,41 @@ func ExampleOption_transformComplex() { // false } +// By default, [Equal] panics when it encounters an unexported field of a +// struct because it cannot safely introspect such fields. When the type is +// owned by the test author, [AllowUnexported] permits comparison of those +// fields by name. +// +// Avoid using [AllowUnexported] on types that you do not control; doing so +// couples tests to internal implementation details that may change. +func ExampleAllowUnexported() { + // account has both an exported and an unexported field. + type account struct { + Name string + balance int64 + } + + x := account{Name: "alice", balance: 100} + y := account{Name: "alice", balance: 100} + z := account{Name: "alice", balance: 200} + + // AllowUnexported permits Equal/Diff to read account.balance. + opt := cmp.AllowUnexported(account{}) + + fmt.Println(cmp.Equal(x, y, opt)) + fmt.Println(cmp.Equal(x, z, opt)) + fmt.Println(cmp.Diff(x, z, opt)) + + // Output: + // true + // false + // cmp_test.account{ + // Name: "alice", + // - balance: 100, + // + balance: 200, + // } +} + type ( Gateway struct { SSID string