Skip to content

Convenient FilterPath functions #75

Description

@dnephin

Hello, I've been using go-cmp for a bit now and I've found that the two most common cases for needing an Option are:

  1. AllowUnexported/IgnoreUnexported - which is already easy to use
  2. A FilterPath for fields that have values set from time.Now() (time.Time, or time.Duration)

It wasn't immediately obvious to me how to create a correct FilterPath filter function. After a quick scan of the godoc my first approach was something like this:

func(path gocmp.Path) bool {		
    return path.Last().String() == ".Elapsed"		
}

This worked, but it seems to me like it could potentially match fields that I don't want it to match if I used it with a large nested structure where multiple types had an Elapsed field.

Digging into the godoc further I noticed that a bunch of the types embedded PathStep, which made me realize that a more correct way of using Path would probably be to iterate over the steps, type assert to the expected type, and compare to Name() or Key().

My next iteration (gotestyourself/gotest.tools#62) looks something like this:

func fieldPathWithTypes(pathspec string) func(gocmp.Path) bool {
	return func(path gocmp.Path) bool {
		spec := strings.Split(pathspec, ".")
		index := 0

		for _, step := range path {
			fieldStep, ok := step.(gocmp.StructField)
			if !ok {
				continue
			}
			if index >= len(spec) || spec[index] != fieldStep.Name() {
				return false
			}
			index++
		}
		return index == len(spec)
	}
}

Which could be made a lot simpler if it's expected that PathStep.String() is stable and wont change between minor versions:

func fieldPathSimple(pathspec string) func(gocmp.Path) bool {
	return func(path gocmp.Path) bool {
		return path.String() == pathspec
	}
}

The same idea could be applied using GoString() if that is considered stable. The idea behind both of these functions is that it's much easier for a reader to understand a dotted path string, than it is to read a long function with a bunch of type assertions.

Questions:

  1. What is the expected/"best practice" way of using PathStep? Is it similar to fieldPathWithTypes ?
  2. Would you be interested in a PR that adds a convenience function for building the PathFilter filter function from a simple string? This could be something like fieldPathWithTypes or it could be more verbose (to match against something like GoString(). I believe the only type that can't be easily translated from a string representation would be Transform.
  3. Would you be interested in a PR that adds one or more examples for using FilterPath (based on feedback from these other questions) ?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions