cmp/cmpopts/ignore.go
func IgnoreSliceElements(discardFunc interface{}) cmp.Option {
	vf := reflect.ValueOf(discardFunc)
	if !function.IsType(vf.Type(), function.ValuePredicate) || vf.IsNil() {
		panic(fmt.Sprintf("invalid discard function: %T", discardFunc))
	}
	return cmp.FilterPath(func(p cmp.Path) bool {
		si, ok := p.Index(-1).(cmp.SliceIndex)
		if !ok {
			return false
		}
		if !si.Type().AssignableTo(vf.Type().In(0)) {
			return false
		}
		vx, vy := si.Values()
		if vx.IsValid() && vf.Call([]reflect.Value{vx})[0].Bool() {
			return true
		}
		if vy.IsValid() && vf.Call([]reflect.Value{vy})[0].Bool() {
			return true
		}
		return false
	}, cmp.Ignore())
}
func IgnoreSliceElements(discardFunc interface{}) cmp.Option {
	vf := reflect.ValueOf(discardFunc)
	if !function.IsType(vf.Type(), function.ValuePredicate) || vf.IsNil() {
		panic(fmt.Sprintf("invalid discard function: %T", discardFunc))
	}
	return cmp.FilterPath(func(p cmp.Path) bool {
		si, ok := p.Index(-1).(cmp.SliceIndex)
		if !ok {
			return false
		}
		if !si.Type().AssignableTo(vf.Type().In(0)) {
			return false
		}
		vx, vy := si.Values()
		if vx.IsValid() && vf.Call([]reflect.Value{vx})[0].Bool() {
			return true
		}
		if vy.IsValid() && vf.Call([]reflect.Value{vy})[0].Bool() {
			return true
		}
		return false
	}, cmp.Ignore())
}
// IgnoreSliceElements returns an Option that ignores elements of []V.
// The discard function must be of the form "func(T) bool" which is used to
// ignore slice elements of type V, where V is assignable to T.
// Elements are ignored if the function reports true.