我正在尝试快速找到两个[]reflect.Type
之间进行比较的方法。现在我有以下内容:
func Equal(left, right []reflect.Type) bool {
if len(left) != len(right) {
return false
}
for i := 0; i < len(left); i++ {
if left[i] != right[i] {
return false
}
}
return true
}
大多数切片都不会改变。因此,如果我能找到一种方法来对它们进行哈希处理,那么我将获得巨大的性能提升。
背景
我正在尝试(为了好玩)使用reflect
包在Go中实现一种函数重载形式。我做的第一件事是将每个专用/重载函数转换为签名类型。
type Signature struct {
Variadic bool
In, Out []reflect.Type
}
我的想法是,当调用重载函数时,我会将参数转换为reflect.Type
切片,然后找到Signature
类型匹配的In
。
这是有效的,但是对于每次比较,这是一个非常慢的线性扫描。如果我可以散列[]reflect.Type
的切片,我可以将其粘贴在地图中并获得恒定的时间查找。
答案 0 :(得分:0)
我最终滥用内置map
为每个reflect.Type
分配唯一ID。然后我使用djb2散列那些。
type TypeCode struct {
seq int64
codes map[reflect.Type]int64
}
func (td *TypeCode) TypeID(t reflect.Type) int64 {
if code, ok := td.codes[t]; ok {
return code
}
td.seq++
td.codes[t] = td.seq
return td.seq
}
func (td *TypeCode) SliceTypeID(tt []reflect.Type) int64 {
id := int64(5381)
for _, t := range tt {
id = ((id << 5) + id) + td.TypeID(t)
}
return id
}
编辑:我切换到基于字符串的方法效率较低,但删除了任何可能的冲突。
type TypeCode struct {
seq int64
codes map[reflect.Type]string
}
func (td *TypeCode) TypeID(t reflect.Type) string {
if code, ok := td.codes[t]; ok {
return code
}
td.seq++
id := strconv.FormatInt(td.seq, 10)
td.codes[t] = id
return id
}
func (td *TypeCode) SliceTypeID(tt []reflect.Type) string {
ids := make([]string, len(tt))
for i := 0; i < len(tt); i++ {
ids[i] = td.TypeID(tt[i])
}
return strings.Join(ids, ".")
}