|
|
@ -71,7 +71,7 @@ func normalizeFloatString(input string, allowNegative bool) string {
|
|
|
|
|
|
|
|
|
|
|
|
func getStructHash(x interface{}) string {
|
|
|
|
func getStructHash(x interface{}) string {
|
|
|
|
raw := make(map[string]string)
|
|
|
|
raw := make(map[string]string)
|
|
|
|
collectTypeFields(reflect.TypeOf(x), raw)
|
|
|
|
collectTypeFieldsAsMap(reflect.TypeOf(x), raw)
|
|
|
|
|
|
|
|
|
|
|
|
h := sha256.New()
|
|
|
|
h := sha256.New()
|
|
|
|
h.Write([]byte(fmt.Sprintf("%v", raw)))
|
|
|
|
h.Write([]byte(fmt.Sprintf("%v", raw)))
|
|
|
@ -79,8 +79,7 @@ func getStructHash(x interface{}) string {
|
|
|
|
return fmt.Sprintf("%x", h.Sum(nil))
|
|
|
|
return fmt.Sprintf("%x", h.Sum(nil))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func collectTypeFields(t reflect.Type, m map[string]string) {
|
|
|
|
func collectTypeFieldsAsMap(t reflect.Type, m map[string]string) {
|
|
|
|
// Return if not struct or pointer to struct.
|
|
|
|
|
|
|
|
if t.Kind() == reflect.Ptr {
|
|
|
|
if t.Kind() == reflect.Ptr {
|
|
|
|
t = t.Elem()
|
|
|
|
t = t.Elem()
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -88,14 +87,12 @@ func collectTypeFields(t reflect.Type, m map[string]string) {
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Iterate through fields collecting names in map.
|
|
|
|
|
|
|
|
for i := 0; i < t.NumField(); i++ {
|
|
|
|
for i := 0; i < t.NumField(); i++ {
|
|
|
|
sf := t.Field(i)
|
|
|
|
sf := t.Field(i)
|
|
|
|
m[sf.Name] = fmt.Sprintf("%v", sf)
|
|
|
|
m[sf.Name] = fmt.Sprintf("%v", sf)
|
|
|
|
|
|
|
|
|
|
|
|
// Recurse into anonymous fields.
|
|
|
|
|
|
|
|
if t.Kind() == reflect.Struct {
|
|
|
|
if t.Kind() == reflect.Struct {
|
|
|
|
collectTypeFields(sf.Type, m)
|
|
|
|
collectTypeFieldsAsMap(sf.Type, m)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|