Last active
January 27, 2023 21:25
-
-
Save carl-mastrangelo/8e0c64e8b4588669857808f37aebcdac to your computer and use it in GitHub Desktop.
Golang hash function
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 characters
// https://play.golang.org/p/auAxrJQ1b1 | |
package main | |
import ( | |
"fmt" | |
"reflect" | |
"unsafe" | |
) | |
type rtype struct { | |
size uintptr | |
ptrdata uintptr // number of bytes in the type that can contain pointers | |
hash uint32 // hash of type; avoids computation in hash tables | |
tflag uint8 // extra type information flags | |
align uint8 // alignment of variable with this type | |
fieldAlign uint8 // alignment of struct field with this type | |
kind uint8 // enumeration for C | |
alg *typeAlg // algorithm table | |
gcdata *byte // garbage collection data | |
str int32 // string form | |
ptrToThis int32 // type for pointer to this type, may be zero | |
} | |
// a copy of runtime.typeAlg | |
type typeAlg struct { | |
hash func(unsafe.Pointer, uintptr) uintptr | |
equal func(unsafe.Pointer, unsafe.Pointer) bool | |
} | |
type iface struct { | |
tab uintptr | |
data unsafe.Pointer | |
} | |
func getalgs(example interface{}, seed uintptr) (hash func(in interface{}) uintptr, equal func(a, b interface{}) bool) { | |
typ := reflect.ValueOf(reflect.TypeOf(example)) | |
rt := *(*rtype)(unsafe.Pointer(typ.Pointer())) | |
alg := rt.alg | |
origiface := *(*iface)(unsafe.Pointer(&example)) | |
origitab := origiface.tab | |
hash = func(in interface{}) uintptr { | |
is := *(*iface)(unsafe.Pointer(uintptr(unsafe.Pointer(&in)))) | |
if is.tab != origitab { | |
panic("wrong type") | |
} | |
return alg.hash(is.data, seed) | |
} | |
equal = func(a, b interface{}) bool { | |
leftiface := *(*iface)(unsafe.Pointer(&a)) | |
rightiface := *(*iface)(unsafe.Pointer(&a)) | |
if leftiface.tab != origitab || rightiface.tab != origitab { | |
panic("wrong type") | |
} | |
return alg.equal(leftiface.data, rightiface.data) | |
} | |
return | |
} | |
func main() { | |
hash, equal := getalgs(2, 0) | |
fmt.Println(hash(4)) | |
hash(1) | |
fmt.Println(equal(*new(int), *new(int))) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment