You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
2.5 KiB

package service
import (
"context"
"math/rand"
pb "verifyCode/api/verifyCode"
)
type VerifyCodeService struct {
pb.UnimplementedVerifyCodeServer
}
func NewVerifyCodeService() *VerifyCodeService {
return &VerifyCodeService{}
}
func (s *VerifyCodeService) GetVerifyCode(ctx context.Context, req *pb.GetVerifyCodeRequest) (*pb.GetVerifyCodeReply, error) {
//log.Info("current verifyCode service Run")
return &pb.GetVerifyCodeReply{
Code: RandCode(int(req.Length), req.Type),
}, nil
}
// RandCode 开放的被调用的方法,用于区分类型
func RandCode(l int, t pb.TYPE) string {
switch t {
case pb.TYPE_DEFAULT:
fallthrough
case pb.TYPE_DIGIT:
// idxBits表示使用4位二进制数就可以表示完chars的索引了
return randCode("0123456789", l, 4)
case pb.TYPE_LETTER:
return randCode("abcdefghijklmnopqrstuvwxyz", l, 5)
case pb.TYPE_MIXED:
return randCode("0123456789abcdefghijklmnopqrstuvwxyz", l, 6)
default:
}
return ""
}
// 随机数的核心方法(优化实现)
// 一次随机多个随机位,分部分多次使用,
// idxBits表示使用4位二进制数就可以表示完chars的索引了
func randCode(chars string, l, idxBits int) string {
// 计算有效的二进制数位,基于 chars 的长度
// 推荐写死因为chars固定对应的位数长度也固定
// 形成掩码mask
// 例如使用低idxBits位00000000000111111
idxMask := 1<<idxBits - 1 // 00001000000 - 1 = 00000111111
// 63 位可以用多少次
idxMax := 63 / idxBits
result := make([]byte, l)
// 生成随机字符,cache:随机位缓存 ;remain:当前还可以用几次
for i, cache, remain := 0, rand.Int63(), idxMax; i < l; {
// 如果使用的剩余次数为0则重新获取随机
if remain == 0 {
cache, remain = rand.Int63(), idxMax
}
// 利用掩码获取cache的低位作为randIndex索引
if randIndex := int(cache & int64(idxMask)); randIndex < len(chars) {
result[i] = chars[randIndex]
i++
}
// 使用下一组随机位。右移会丢掉先前的低位高位补0
cache >>= idxBits
remain--
}
return string(result)
}
// 随机的核心方法(简单的实现)
//func randCode(chars string, l int) string {
// charsLen := len(chars)
// // 结果
// result := make([]byte, l)
// // 根据目标长度,进行循环
// for i := 0; i < l; i++ {
// // 核心函数 rand.Intn() 生成[0, n)的整型随机数
// randIndex := rand.Intn(charsLen)
// // 字符串的单个字符是uint8类型即byte类型,因此可以赋值
// result[i] = chars[randIndex]
// }
// return string(result)
//}