Convenient FilterPath functions
- Dominant language
- Go
- Stars
- 4.7k
- Forks
- 243
- PR merge metrics
- No merged PRs in 30d
Description
Hello, I've been[ using `go-cmp`](https://godoc.org/github.com/gotestyourself/gotestyourself/assert#DeepEqual) 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:
```go
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 (https://github.com/gotestyourself/gotestyourself/pull/62) looks something like this:
```go
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:
```go
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) ?
Contributor guide
Assessment
This issue has not been assessed yet.