@@ -91,6 +91,11 @@ func Hash(v interface{}, opts *HashOptions) (uint64, error) {
91
91
// Reset the hash
92
92
opts .Hasher .Reset ()
93
93
94
+ // Fast path for strings.
95
+ if s , ok := v .(string ); ok {
96
+ return hashString (opts .Hasher , s )
97
+ }
98
+
94
99
// Create our walker and walk the structure
95
100
w := & walker {
96
101
h : opts .Hasher ,
@@ -130,6 +135,21 @@ func (w *walker) hashDirect(v any) (uint64, error) {
130
135
return w .h .Sum64 (), err
131
136
}
132
137
138
+ // A direct hash calculation used for strings.
139
+ func (w * walker ) hashString (s string ) (uint64 , error ) {
140
+ return hashString (w .h , s )
141
+ }
142
+
143
+ // A direct hash calculation used for strings.
144
+ func hashString (h hash.Hash64 , s string ) (uint64 , error ) {
145
+ h .Reset ()
146
+
147
+ // io.WriteString uses io.StringWriter if it exists, which is
148
+ // implemented by e.g. github.com/cespare/xxhash.
149
+ _ , err := io .WriteString (h , s )
150
+ return h .Sum64 (), err
151
+ }
152
+
133
153
func (w * walker ) visit (v reflect.Value , opts * visitOpts ) (uint64 , error ) {
134
154
t := reflect .TypeOf (0 )
135
155
@@ -405,14 +425,7 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
405
425
return h , nil
406
426
407
427
case reflect .String :
408
- // Directly hash
409
- w .h .Reset ()
410
-
411
- // io.WriteString uses io.StringWriter if it exists, which is
412
- // implemented by e.g. github.com/cespare/xxhash.
413
- _ , err := io .WriteString (w .h , v .String ())
414
- return w .h .Sum64 (), err
415
-
428
+ return w .hashString (v .String ())
416
429
default :
417
430
return 0 , fmt .Errorf ("unknown kind to hash: %s" , k )
418
431
}
0 commit comments