- 日常的网站开发中,会遇到网站的促销活动,就有涉及到邀请好礼的功能
- 成功邀请好友,则获取相应奖励,这时候,就有邀请码的需求
- 邀请码要求每个用户唯一
方法一. 可根据用户的uid生成邀请码 方法二. 邀请码可根据某个初始化id生成,用户主动请求,生成code,绑定uid- 方法二,这种方式,需额外记录uid和code关系
- 方法一,根据uid生成,也可根据code反推出uid,不用额外查询,比较方便
- 记录方法一的实现
- 由长数字转换为特定长度的code,首先需确定code的字符范围
- 可转换为 0-9A-Z 36进制数,或者更多字符可添加小写字符
- 本次实现 转换为 32进制数
- 去掉0 1 和 o 容易混淆的字符和补位字符F,剩余32字符
php实现
/** * Class ShareCodeUtils * * 邀请码生成器,基本原理 * 1)参数用户ID * 2)使用自定义进制转换之后为:V * 3)最小code长度为6位,若不足则在后面添加分隔字符'F':VF * 4)在VF后面再随机补足4位,得到形如 VFAADD * 5)反向转换时以'F'为分界线,'F'后面的不再解析 */ class ShareCodeUtils { // 32个进制字符(0,1 没加入,容易和 o l 混淆,O 未加入,F 未加入,用于补位) // 顺序可进行调整, 增加反推难度 private static $base = ['H', 'V', 'E', '8', 'S', '2', 'D', 'Z', 'X', '9', 'C', '7', 'P','5', 'I', 'K', '3', 'M', 'J', 'U', 'A', 'R', '4', 'W', 'Y', 'L', 'T', 'N', '6', 'B', 'G', 'Q']; // F为补位字符,不能和上述字符重复 private static $pad = "F"; // 进制长度 private static $decimal_len = 32; // 生成code最小长度 private static $code_min_len = 6; /** * id转为code * 相除去模法 * * @param $id * @return string */ public static function idToCode($id) { $result = ""; while (floor($id / static::$decimal_len) > 0){ $index = $id % static::$decimal_len; $result.= static::$base[$index]; $id = floor($id / static::$decimal_len); } $index = $id % static::$decimal_len; $result.= static::$base[$index]; // code长度不足,则随机补全 $code_len = strlen($result); if ($code_len 27 * 8 ---> 3 * 进制转换 27*32(0) + 3*32(1) = 123 * 32(0) ---> 32的0次方 * 32(1) ---> 32的1次方 * * @param $code * @return string */ public static function codeToId($code) { $result = 0; $base_flip_map = array_flip(static::$base); $is_pad = strpos($code, static::$pad); if (!empty($is_pad)) { $len_real = $is_pad; } else { $len_real = strlen($code); } for ($i = 0; $i
go实现
package main import ( "errors" "fmt" "math/rand" "strings" "time" ) type code struct { base string // 进制的包含字符, string类型 decimal uint64 // 进制长度 pad string // 补位字符,若生成的code小于最小长度,则补位+随机字符, 补位字符不能在进制字符中 len int // code最小长度 } // idתcode func (c *code) idToCode (id uint64) string { mod := uint64(0) res := "" for id!=0 { mod = id % c.decimal id = id / c.decimal res += string(c.base[mod]) } resLen := len(res) if resLen
go实现2
package main import( "container/list" "errors" "fmt" ) var baseStr string = "HVE8S2DZX9C7P5IK3MJUAR4WYLTN6BGQ" var base [] byte = []byte(baseStr) var baseMap map[byte] int func InitBaseMap(){ baseMap = make(map[byte]int) for i, v := range base { baseMap[v] = i } } func Base34(n uint64)([]byte){ quotient := n mod := uint64(0) l := list.New() for quotient != 0 { //fmt.Println("---quotient:", quotient) mod = quotient%32 quotient = quotient/32 l.PushFront(base[int(mod)]) //res = append(res, base[int(mod)]) //fmt.Printf("---mod:%d, base:%s\n", mod, string(base[int(mod)])) } listLen := l.Len() if listLen >= 6 { res := make([]byte,0,listLen) for i := l.Front(); i != nil ; i = i.Next(){ res = append(res, i.Value.(byte)) } return res } else { res := make([]byte,0,6) for i := 0; i =0; i-- { v, ok := baseMap[str[i]] if !ok { fmt.Printf("") return 0, errors.New("character is not base") } var b uint64 = 1 for j:=uint64(0); j
- 本次实现由 php 和 go 两种语言实现
- 最大的心得就是 go中的 类型转换是比较麻烦的,因为都是强类型
- 和php 还不太一样
- 但也算是进一步熟悉了go的语法代码
来源:博客园
作者:糖糖果
链接:https://www.cnblogs.com/fanfan259/p/11423288.html