go-test / deep

Golang deep variable equality test that returns human-readable differences
MIT License
743 stars 54 forks source link

Proposal: type specific hooks #64

Open dionysius opened 1 week ago

dionysius commented 1 week ago

I understand that it doesn't make sense to go in and try to support all possible core-ish types. E.g. like json.RawMessage as in #62.

Requesting an Equal method for the parent type may not be the best way to solve the culprit, a few caveats:

What I've seen in different other utilities is to offer a Hook for a type, which could be what is just missing. deep doesn't need to understand the type except to provide the framework for these hooks and this also allows to prototype a compare functions also for foreign types.

Examples:

deep already uses the package reflect, so there's no additional package needed.

Idea very rough from mind and may be incorrect. Good enough to show the idea:

import "reflect"

// signature of an equal func
type EqualFunc func(a, b reflect.Value) (bool, error)

// holds all the provided custom equal funcs
var customEqualFuncs map[reflect.Type]EqualFunc 

// add a custom equal func
func SetEqualFunc(t reflect.Type, f EqualFunc ) {
  customEqualFuncs[t] = f
}

// during equal() check whether a custom equal method exists
func equal(a, b interface{}) ... {
  ...
  // ^ has no Equal method, check if a custom equal func exists
  t := reflect.TypeOf(a)
  if f, exists := customEqualFuncs[t]; exists {
    isequal, err := f(reflect.ValueOf(a),reflect.ValueOf(b))
    ...
    return ...
  }
}

Would be used like:

deep.SetEqualFunc(reflect.TypeOf(json.RawMessage{}), func ... {
   ....
   return isequal, iserr
}

Missing above: diff return, which would need to be incorporated in the idea as well

Options to explore for EqualFunc:


Is such a hook a fitting candidate for deep in your opinion?