「Go工具箱」一个将非负整数转换成唯一、无序ID的工具:hashids

367次阅读  |  发布于2年以前

今天给大家推荐的工具是hashids。该工具可以将一个正整数转换成长度较短、唯一且不连续的ID值。一般适用于生成用户ID,但又不想用有规律的ID的场景。

原理分析:将长字符串转换成短字符串的本质是进制转换。将小进制数往大进制数上转换就会变短,将大进制数往小进制数上转换就会变长。比如将一个二进制数转换成十进制就可以将二进制数变短。如下将1010转换成十进制就是 10,转换成十六进制就是a。该hashids包的原理也是一样,是基于62进制进行转换的。如下:

func hash(input int64) []rune{
  //a-z及A-Z及0-9共62个数
  var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
  for {
    //通过取余法进行进制转换
    r := alphabet[input%int64(len(alphabet))]
    result = append(result, r)
    input /= int64(len(alphabet))
    if input == 0 {
      break
    }
  }
  return result
}

无序性是通过Fisher–Yates shuffle的算法将alphabet进行重排得到。该算法可以参考文末的参考链接,非常简单。

该包是对非负整数产生唯一ID的。个人认为是因为通过取余的方式进行进制转换的原理,那么负数和正数可能会产生同样的余数而导致非唯一性。

该包特点:

基本使用


  hd := hashids.NewData()
  hd.Salt = "my salt"
  h, _ := hashids.NewWithData(hd)
  id, _ := h.Encode([]int{1}) //只要这里的ID或salt值不一样,最终的id就不一样
  fmt.Println(id) // 最终输出 OL

设置生成最短ID的位数,如下设置最小长度是8位:


  hd := hashids.NewData()
  hd.Salt = "my salt"
  hd.MinLength = 8
  h, _ := hashids.NewWithData(hd)
  id, _ := h.Encode([]int{1}) //只要这里的ID或salt值不一样,最终的id就不一样
  fmt.Println(id) // 最终输出 On5OLgYy

更多项目详情请查看如下链接:

开源项目地址:https://github.com/speps/go-hashids

开源项目作者:speps

参考链接:

Fisher–Yates shuffle算法:https://zhuanlan.zhihu.com/p/259652066

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8