Генерирование случайного массива байтов с фиксированной длиной в Go
У меня есть байтовый массив с фиксированной длиной 4.
token := make([]byte, 4)
Мне нужно установить каждый байт на случайный байт. Как я могу это сделать, в самом эффективном? Методы math/rand
не предоставляют функцию Random Byte, насколько мне известно.
Возможно, есть встроенный способ, или мне нужно создать случайную строку и преобразовать ее в массив байтов?
Ответы
Ответ 1
Пакет rand
import "math/rand"
func Читать
func Read(p []byte) (n int, err error)
Чтение генерирует случайные байты len (p) из источника по умолчанию и записывает их в p. Он всегда возвращает len (p) и ошибку nil.
f unc (* Rand) Читать
func (r *Rand) Read(p []byte) (n int, err error)
Чтение генерирует случайные байты len (p) и записывает их в p. Так всегда возвращает len (p) и ошибку nil.
Например,
package main
import (
"math/rand"
"fmt"
)
func main() {
token := make([]byte, 4)
rand.Read(token)
fmt.Println(token)
}
Вывод:
[187 163 35 30]
Ответ 2
Go 1.6 добавил новую функцию в пакет math/rand
:
func Read(p []byte) (n int, err error)
который заполняет переданный кусочек byte
случайными данными. Используя этот rand.Read()
:
token := make([]byte, 4)
if _, err := rand.Read(token); err != nil {
// Handle err
}
fmt.Println(token)
rand.Read()
имеет 2 возвращаемых значения: количество "прочитанных" байтов и (необязательная) error
. Это должно соответствовать общему интерфейсу io.Reader
, но документация rand.Read()
гласит, что (несмотря на свою подпись) он на самом деле никогда не вернет ошибку non- nil
, поэтому мы можем не проверять ее, что упрощает ее к этому:
token := make([]byte, 4)
rand.Read(token){
fmt.Println(token)
Не забудьте вызвать rand.Seed()
чтобы правильно инициализировать его перед использованием пакета math/rand
, например:
rand.Seed(time.Now().UnixNano())
Примечание: до Go 1.6 не было никакой функции math/rand.Read()
, но была (и есть crypto/rand.Read()
функция crypto/rand.Read()
, но пакет crypto/rand
реализует криптографически безопасный генератор псевдослучайных чисел, так что это намного медленнее, чем math/rand
.
Ответ 3
Использование math.Rand означает, что вы используете системный CSPRNG, предоставляемый вашей операционной системой. Это означает использование /dev/urandom/и Windows CryptGenRandom API. Gos crypto/rand package, к счастью, абстрагирует эти детали реализации, чтобы минимизировать риск ошибиться.
import(
"crypto/rand"
"encoding/base64"
)
// GenerateRandomBytes returns securely generated random bytes.
// It will return an error if the system secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomBytes(n int) ([]byte, error) {
b := make([]byte, n)
_, err := rand.Read(b)
// Note that err == nil only if we read len(b) bytes.
if err != nil {
return nil, err
}
return b, nil
}