go 随机数 范围_一步步提升Go语言生成随机字符串的效率

假如我们要生成一个固定长度的随机字符串,包含大小写字母,没有数字,没有特殊字符串,那么我们怎么做呢?需要怎样优化,才会更简单,更高效?在最终的方案之前,我们看看最常见的写法是怎样的,然后是如何一步步演进到最终的高效率方案的。好吧,先看下最原始的方案。

常见做法(Runes)

func init() {
    
    rand.Seed(time.Now().UnixNano())
}

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func RandStringRunes(n int) string {
    
    b := make([]rune, n)
    for i := range b {
    
        b[i] = letterRunes[rand.Intn(len(letterRunes))]
    }
    return string(b)
}

这个实现比较简单,二十六字母(大小写),然后随机取数,获得随机字符串。

Bytes改进

我们在最开始的时候进行了假设,我们的随机字符串只包含大小写字母,这样的话,我们发现没有必要使用rune类型存储,因为在Golang(Go语言)UTF-8编码下,英文字母和byte字节是一对一的。byte的本质是uint8类型,而rune本质是int32类型。我们改进后的代码如下:

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

func RandStringBytes(n int) string {
    
    b := make([]byte, n)
    for i := range b {
    
        b[i] = letterBytes[rand.Intn(len(letterBytes))]
    }
    return string(b)
}

仔细看上面的代码,我们不光对rune类型进行了改进,还把原来的letter变量变成了常量,这样len(letterBytes)也是一个常量,代码的效率将大大提升。

余数改进

我们前面的方案都是通过调用rand.Intn()生成的随机字符,这个rand.Intn()其实是委托调用的Rand.Intn(),而Rand.Intn()最终又是调用的Rand.Int31n()实现。相比我们直接调用rand.Int63()来说,rand.Intn()要慢很多。

所以我们可以把rand.Intn()换成rand.Int63()来提高效率,为了不超过letterBytes的索引范围,我们使用余数来保证。

func RandStringBytesRmndr(n int) string {
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值