哈希反射。类型

时间:2018-04-03 15:54:48

标签: go reflection hash

我正在尝试快速找到两个[]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的切片,我可以将其粘贴在地图中并获得恒定的时间查找。

1 个答案:

答案 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, ".")
}