Last active
July 26, 2024 19:23
Revisions
-
StevenACoffman revised this gist
Jul 26, 2024 . 1 changed file with 20 additions and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -78,6 +78,23 @@ If you can't or don't want to go with the above solutions, you can always create Try this on the [Go Playground][4]. ## 4. Use a library like github.com/google/go-cmp/cmp/cmpopts For testing purposes, you can use [cmpopts][7] - this allows (exported) fields to be ignored when `cmp.Equal` from the [cmp][8] package is used. func main() { a := test{"testName", time.Now().Local().String()} // after some time b := test{"testName", time.Now().Local().String()} fmt.Printf("a: %#v\nb: %#v\n", a, b) if !cmp.Equal(a, b, cmpopts.IgnoreFields(test{}, "Time")) { log.Fatalf("mismatching data") } } **Notes:** This isn't "friendly" at first, as the custom `compare()` function requires you to check all involved fields, but its implementation may use the above methods, e.g. (try it on the [Go Playground][5]): @@ -105,4 +122,6 @@ You could also pass pointers to `compare()` to avoid copying the original struct [3]: https://play.golang.org/p/rIOBVWBOhB [4]: https://play.golang.org/p/LJ4cVhyGui [5]: https://play.golang.org/p/jRxOQyPXAM [6]: https://play.golang.org/p/4xI4P0VDRu [7]: https://pkg.go.dev/github.com/google/go-cmp/cmp/cmpopts [8]: https://pkg.go.dev/github.com/google/go-cmp@v0.5.8#section-readme -
StevenACoffman revised this gist
Jul 26, 2024 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,5 @@ From https://stackoverflow.com/questions/47134293/compare-structs-except-one-field-golang ## 1. With embedding One option would be to group fields that should take part in the comparison into a different struct which you can embed in your original. When doing the comparison, just compare the embedded fields: -
StevenACoffman created this gist
Jul 26, 2024 .There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,106 @@ ## 1. With embedding One option would be to group fields that should take part in the comparison into a different struct which you can embed in your original. When doing the comparison, just compare the embedded fields: type Person struct { Name string Age int } type Doc struct { Person Created time.Time } func main() { d1 := Doc{ Person: Person{"Bob", 21}, Created: time.Now(), } time.Sleep(time.Millisecond) d2 := Doc{ Person: Person{"Bob", 21}, Created: time.Now(), } fmt.Println(d1 == d2) // false fmt.Println(d1.Person == d2.Person) // true } Try it on the [Go Playground][1]. If the struct does not contain pointers, slices, maps etc., you can simply compare the embedded values using `==`. Otherwise use `reflect.DeepEqual()` to compare them. ## 2. Temporarily modifying the excludable fields You may also choose to temporarily modify the fields you don't want to compare: _make them equal_ so the comparison result will only depend on the rest of the fields: a := test{"testName", time.Now().Format(time.StampMilli)} time.Sleep(time.Millisecond) b := test{"testName", time.Now().Format(time.StampMilli)} // Save and make excluded fields equal: old := a.time a.time = b.time fmt.Println(a.name == b.name) // true fmt.Println(reflect.DeepEqual(a, b)) // true // Restore: a.time = old Try it on the [Go Playground][2]. Another variation is to make a copy of one of the struct values, and modify and compare that to the other, so no need to restore the original, also this is "more concurrent-friendly": // Make copies and make excluded fields equal: a2 := a a2.time = b.time fmt.Println(a2.name == b.name) // true fmt.Println(reflect.DeepEqual(a2, b)) // true Try this on the [Go Playground][3]. ## 3. Implement your own, custom comparison If you can't or don't want to go with the above solutions, you can always create your own: func compare(a, b test) bool { return a.name == b.name } fmt.Println(a.name == b.name) // true fmt.Println(compare(a, b)) // true Try this on the [Go Playground][4]. **Notes:** This isn't "friendly" at first, as the custom `compare()` function requires you to check all involved fields, but its implementation may use the above methods, e.g. (try it on the [Go Playground][5]): func compare(a, b test) bool { a.time = b.time // We're modifying a copy, so no need to make another copy return reflect.DeepEqual(a, b) } You could also pass pointers to `compare()` to avoid copying the original struct, e.g. (try it on the [Go Playground][6]): fmt.Println(a.name == b.name) // true fmt.Println(compare(&a, &b)) // true func compare(a, b *test) bool { a2 := new(test) *a2 = *a a2.time = b.time return reflect.DeepEqual(a2, b) } [1]: https://play.golang.org/p/KNMfSXoj9P [2]: https://play.golang.org/p/3OKJ6gi_Hl [3]: https://play.golang.org/p/rIOBVWBOhB [4]: https://play.golang.org/p/LJ4cVhyGui [5]: https://play.golang.org/p/jRxOQyPXAM [6]: https://play.golang.org/p/4xI4P0VDRu