@ -98,10 +98,14 @@ func (s Sum) String() string {
}
}
var (
var (
o nce sync . Once
seedO nce sync . Once
seed uint64
seed uint64
)
)
func initSeed ( ) {
seed = uint64 ( time . Now ( ) . UnixNano ( ) )
}
func ( h * hasher ) sum ( ) ( s Sum ) {
func ( h * hasher ) sum ( ) ( s Sum ) {
h . bw . Flush ( )
h . bw . Flush ( )
// Sum into scratch & copy out, as hash.Hash is an interface
// Sum into scratch & copy out, as hash.Hash is an interface
@ -121,9 +125,7 @@ func Hash(v any) (s Sum) {
h := hasherPool . Get ( ) . ( * hasher )
h := hasherPool . Get ( ) . ( * hasher )
defer hasherPool . Put ( h )
defer hasherPool . Put ( h )
h . reset ( )
h . reset ( )
once . Do ( func ( ) {
seedOnce . Do ( initSeed )
seed = uint64 ( time . Now ( ) . UnixNano ( ) )
} )
h . hashUint64 ( seed )
h . hashUint64 ( seed )
h . hashValue ( reflect . ValueOf ( v ) , false )
h . hashValue ( reflect . ValueOf ( v ) , false )
return h . sum ( )
return h . sum ( )
@ -425,9 +427,9 @@ func (h *hasher) hashValueWithType(v reflect.Value, ti *typeInfo, forceCycleChec
}
}
type mapHasher struct {
type mapHasher struct {
h hasher
h hasher
val valueCache // re-usable values for map iteration
val Key, valElem valueCache // re-usable values for map iteration
iter reflect . MapIter // re-usable map iterator
iter reflect . MapIter // re-usable map iterator
}
}
var mapHasherPool = & sync . Pool {
var mapHasherPool = & sync . Pool {
@ -461,8 +463,12 @@ func (h *hasher) hashMap(v reflect.Value, ti *typeInfo, checkCycles bool) {
defer iter . Reset ( reflect . Value { } ) // avoid pinning v from mh.iter when we return
defer iter . Reset ( reflect . Value { } ) // avoid pinning v from mh.iter when we return
var sum Sum
var sum Sum
k := mh . val . get ( v . Type ( ) . Key ( ) )
if v . IsNil ( ) {
e := mh . val . get ( v . Type ( ) . Elem ( ) )
sum . sum [ 0 ] = 1 // something non-zero
}
k := mh . valKey . get ( v . Type ( ) . Key ( ) )
e := mh . valElem . get ( v . Type ( ) . Elem ( ) )
mh . h . visitStack = h . visitStack // always use the parent's visit stack to avoid cycles
mh . h . visitStack = h . visitStack // always use the parent's visit stack to avoid cycles
for iter . Next ( ) {
for iter . Next ( ) {
k . SetIterKey ( iter )
k . SetIterKey ( iter )