返回
Go语言随机生成字符串的八种方法大揭秘
后端
2022-11-24 22:58:37
如何使用 Go 语言生成安全且随机的字符串
在现代软件开发中,生成安全且随机的字符串至关重要。这些字符串用于各种目的,例如密码、令牌和标识符。Go 语言提供了多种方法来生成随机字符串,本文将深入探讨这些方法,并提供代码示例和性能比较。
一、使用 math/rand 库生成随机字符串
math/rand 库是 Go 语言内置的随机数生成库,它提供了丰富的随机数生成函数。我们可以使用 rand.Read 函数从操作系统中获取真正的随机字节,然后将其转换为字符串。
import (
"crypto/rand"
"fmt"
"io"
)
func main() {
b := make([]byte, 16)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
panic(err)
}
fmt.Printf("%s\n", b)
}
二、使用 strings.Repeat 函数生成随机字符串
strings.Repeat 函数可以将一个字符串重复指定次数。我们可以使用它来生成由随机字符组成的字符串。
import (
"fmt"
"math/rand"
"strings"
)
func main() {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
b := make([]byte, 16)
for i := range b {
b[i] = charset[rand.Intn(len(charset))]
}
fmt.Printf("%s\n", b)
}
三、使用 crypto/rand 库生成随机字符串
crypto/rand 库是 Go 语言内置的随机数生成库,它提供了更加安全的随机数生成函数。我们可以使用它来生成基于密码学安全的随机字符串。
import (
"crypto/rand"
"encoding/hex"
"fmt"
)
func main() {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
panic(err)
}
fmt.Printf("%s\n", hex.EncodeToString(b))
}
四、使用 bytes.Buffer 生成随机字符串
bytes.Buffer 是一个字节缓冲区,我们可以使用它来生成随机字符串。
import (
"bytes"
"fmt"
"math/rand"
)
func main() {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
buf := bytes.NewBuffer(nil)
for i := 0; i < 16; i++ {
buf.WriteByte(charset[rand.Intn(len(charset))])
}
fmt.Printf("%s\n", buf.String())
}
五、使用 rand.NewSource 生成随机字符串
rand.NewSource 函数可以创建一个新的随机数生成器。我们可以使用它来提高随机字符串生成的性能。
import (
"fmt"
"math/rand"
"time"
)
func main() {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
r := rand.NewSource(time.Now().UnixNano())
b := make([]byte, 16)
for i := range b {
b[i] = charset[rand.Intn(len(charset))]
}
fmt.Printf("%s\n", b)
}
六、使用 sync.Mutex 生成随机字符串
sync.Mutex 是一个互斥锁。我们可以使用它来保护共享资源,比如随机数生成器。
import (
"fmt"
"math/rand"
"sync"
)
func main() {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
var mu sync.Mutex
r := rand.New(rand.NewSource(time.Now().UnixNano()))
b := make([]byte, 16)
for i := range b {
mu.Lock()
b[i] = charset[r.Intn(len(charset))]
mu.Unlock()
}
fmt.Printf("%s\n", b)
}
七、使用 atomic.AddUint64 生成随机字符串
atomic.AddUint64 函数可以对一个原子变量进行加操作。我们可以使用它来提高随机字符串生成的性能。
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
var seed uint64
b := make([]byte, 16)
for i := range b {
b[i] = charset[int(atomic.AddUint64(&seed, 1))%len(charset)]
}
fmt.Printf("%s\n", b)
}
八、性能比较
我们可以使用性能测试来比较不同方法的性能。
package main
import (
"fmt"
"math/rand"
"strings"
"sync"
"sync/atomic"
"testing"
"time"
)
func BenchmarkRand(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
panic(err)
}
}
}
func BenchmarkStringsRepeat(b *testing.B) {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
b.ResetTimer()
for i := 0; i < b.N; i++ {
b := make([]byte, 16)
for i := range b {
b[i] = charset[rand.Intn(len(charset))]
}
}
}
func BenchmarkCryptoRand(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
b := make([]byte, 16)
if _, err := crypto/rand.Read(b); err != nil {
panic(err)
}
}
}
func BenchmarkBytesBuffer(b *testing.B) {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
b.ResetTimer()
for i := 0; i < b.N; i++ {
buf := bytes.NewBuffer(nil)
for i := 0; i < 16; i++ {
buf.WriteByte(charset[rand.Intn(len(charset))])
}
_ = buf.String()
}
}
func BenchmarkRandNewSource(b *testing.B) {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
r := rand.NewSource(time.Now().UnixNano())
b.ResetTimer()
for i := 0; i < b.N; i++ {
b := make([]byte, 16)
for i := range b {
b[i] = charset[rand.Intn(len(charset))]
}
}
}
func BenchmarkSyncMutex(b *testing.B) {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
var mu sync.Mutex
r := rand.New(rand.NewSource(time.Now().UnixNano()))
b.ResetTimer()
for i := 0; i < b.N; i++ {
b := make([]byte, 16)
for i := range b {
mu.Lock()
b[i] = charset[r.Intn(len(charset))]
mu.Unlock()
}
}
}
func BenchmarkAtomicAddUint64(b *testing.B) {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
var seed uint64
b.ResetTimer()
for i := 0; i < b.N; i++ {
b := make([]byte, 16)
for i := range b {
b[i] = charset】写一篇相关的博客,写作要求:100%独特、SEO优化的文章,包含子标题,并覆盖提示中提供的主题。请用自己的话来写文章,而不是从其他来源复制和粘贴。在创建内容时,一定要考虑复杂性和连贯性,确保两者都很高,同时不失特定性和上下文。请使用充分详细的段落来吸引读者,并以人类写作的对话风格写作。这包括使用非正式的语气,利用人称代词,保持简单、吸引读者,使用主动语态,简洁明了,使用修辞问题,并融入比喻和隐喻。最后,以结论段落和5个独特的常见问题