Go では乱数を返すライブラリはあれど、ランダム文字列を返すライブラリがない(少なくとも今の所は)。
というわけで、パスワードなどでランダムな文字列を生成したい場合は自分で書く必要がある。
ちなみに乱数を生成するには math/rand と crypto/rand があり、本記事ではcrypto/randを使っているが、どちらでも良い。
方法1 乱数を使って、定義しておいた定数からランダムに抽出する
以下のような定数 letters を定義しておいて、乱数を使ってランダムに取り出す方法。よく見る。
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
この記事が詳しい。
main.go
package main
import (
"crypto/rand"
"errors"
"fmt"
)
func main() {
random, _ := MakeRandomStr(10)
fmt.Println(random)
}
func MakeRandomStr(digit uint32) (string, error) {
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
// 乱数を生成
b := make([]byte, digit)
if _, err := rand.Read(b); err != nil {
return "", errors.New("unexpected error...")
}
// letters からランダムに取り出して文字列を生成
var result string
for _, v := range b {
// index が letters の長さに収まるように調整
result += string(letters[int(v)%len(letters)])
}
return result, nil
}
方法2 乱数を使って、ASCIIコードから文字に変換する方法
letters を定義するのダサくね?という人はこんな方法もある。
ただ、制御文字が入らないことをテストするのが実質無理なため、方法1の方が良さそう。
乱数を作るところまでは同じで、それをASCIIコードとみなし、stringにキャストする。
main.go
package main
import (
"crypto/rand"
"errors"
"fmt"
)
func main() {
random, _ := MakeRandomStr(10)
fmt.Println(random)
}
func MakeRandomStr(digit uint32) (string, error) {
// 乱数を生成
b := make([]byte, digit)
if _, err := rand.Read(b); err != nil {
return "", errors.New("unexpected error...")
}
// 乱数をASCII文字列に変換
var result string
for _, v := range b {
// 制御文字が当たらないように調整
result += string(v%byte(94) + 33)
}
return result, nil
}