Go’da tasodifiy qiymatlar yaratish
Tasodifiy qiymatlar o‘yin, simulyatsiya, test ma’lumoti, elementlarni aralashtirish va xavfsizlik tokenlarini yaratishda ishlatiladi. Lekin barcha tasodifiy generatorlar bir xil vazifa uchun mo‘ljallanmagan.
Go’da ikki asosiy paket bor:
math/rand— tez, psevdotasodifiy qiymatlar uchun;crypto/rand— taxmin qilish qiyin bo‘lgan, kriptografik xavfsiz qiymatlar uchun.
Ularning nomi bir xil bo‘lsa ham, xavfsizlik xususiyatlari boshqa. Session ID, parolni tiklash tokeni yoki API kalitini math/rand bilan yaratish xavfli.
Psevdotasodifiy son nima?
Psevdotasodifiy sonlar generatori (PRNG) boshlang‘ich holat va algoritm asosida sonlar ketma-ketligini hisoblaydi. Natijalar tasodifiy ko‘rinadi, ammo bir xil boshlang‘ich qiymat (seed) bir xil generatorga berilsa, ketma-ketlik takrorlanadi.
Bu xususiyat test va simulyatsiyada foydali. Xato faqat muayyan ketma-ketlikda yuz bersa, o‘sha seed bilan holatni qayta yaratish mumkin. Hujumchi taxmin qilmasligi kerak bo‘lgan qiymatlar uchun esa bu xususiyat mos emas.
math/rand bilan ishlash
math/randning paket darajasidagi funksiyalari avtomatik boshlang‘ich holatga ega. Zamonaviy Go versiyalarida dasturni har ishga tushirganda qo‘lda time.Now().UnixNano() bilan global seed o‘rnatish kerak emas.
Mumkin bo‘lgan natija:
rand.Intn(100) [0, 100) yarim ochiq oraliqdan qiymat qaytaradi. Demak, eng kichik qiymat 0, eng kattasi 99. Natija har ishga tushirishda farq qilishi mumkin.
Warning
rand.Intn(n) uchun n musbat bo‘lishi shart. n <= 0 bo‘lsa, dastur panic qiladi. Tashqaridan kelgan chegarani avval tekshiring.
Ixtiyoriy oraliqdan son olish
mindan maxgacha, ikkala chegara ham kiradigan son kerak bo‘lsa, oraliq kengligi max-min+1 bo‘ladi:
Mumkin bo‘lgan natija:
Funksiya 10, 11, 12, 13, 14 yoki 15 qiymatlaridan birini qaytaradi. min > max holati tekshirilgani uchun Intn()ga noto‘g‘ri argument uzatilmaydi.
Bu formulada ekstremal int qiymatlari ishlatilsa, max-min+1 overflow qilishi mumkin. Oddiy kichik diapazonlarda muammo yo‘q. Ishonchsiz tashqi qiymatlar yoki juda katta chegaralar bilan ishlaganda ayirishdan oldin diapazonni cheklash kerak.
Takrorlanuvchi natija uchun lokal generator
Testda bir xil ketma-ketlik kerak bo‘lsa, global rand.Seed() o‘rniga alohida generator yarating:
Natija:
rand.NewSource(42) bir xil boshlang‘ich holatli ikkita manba yaratadi. Har bir generatorga metodlar bir xil tartibda chaqirilgani uchun juft natijalar teng chiqadi. Bitta generatorga qo‘shimcha chaqiruv qilinsa, ularning holati turlicha bo‘lib qoladi.
Paket darajasidagi rand.Seed() eskirgan. Joriy Go versiyalarida u global generatorni boshqarish uchun ishlatilmasligi kerak. Deterministik oqim zarur bo‘lsa, rand.New(rand.NewSource(seed)) aniqroq va boshqa kodga ta’sir qilmaydi.
Warning
rand.NewSource() qaytargan manba va undan yaratilgan *rand.Rand bir nechta goroutine tomonidan bir vaqtda ishlatish uchun xavfsiz emas. Har bir goroutine uchun alohida generator ishlating yoki murojaatni mutex bilan himoyalang. Paket darajasidagi funksiyalar esa concurrent ishlatishga mos.
Elementlarni aralashtirish
rand.Shuffle() slice elementlarining tartibini o‘zgartiradi:
Mumkin bo‘lgan natija:
Callback i va j indekslaridagi elementlarni almashtiradi. Slice’ning o‘zi o‘zgaradi, nusxa yaratilmaydi. Bu test ma’lumotlarini aralashtirish yoki o‘yin navbatini belgilashda foydali. Xavfsizlikka oid tasodifiy tartib uchun math/rand yetarli emas.
crypto/rand bilan xavfsiz son olish
crypto/rand operatsion tizim taqdim etgan kriptografik tasodifiylik manbasidan foydalanadi. Unga foydalanuvchi seed bermaydi.
Mumkin bo‘lgan natija:
rand.Int() [0, max) oraliqdan bir xil ehtimolli *big.Int qaytaradi. big.NewInt(101) sabab natija 0dan 100gacha bo‘ladi. max <= 0 bo‘lsa, funksiya panic qiladi. Shu sababli dinamik chegarani oldindan tekshirish kerak.
Paketlar nomi to‘qnashsa, alias ishlatish mumkin:
Shundan keyin kodda cryptorand.Int() va mathrand.Intn() yoziladi. Bu parcha import nomlarini ajratish usulini ko‘rsatadi; alohida dastur emas.
Xavfsiz token yaratish
Token uchun tasodifiy baytlarni matnga kodlash keng tarqalgan usul:
Natija:
16 tasodifiy bayt 128 bit tasodifiylik beradi. Har bir bayt hexadecimal ko‘rinishda ikkita belgi bilan yozilgani uchun token uzunligi doim 32 belgi bo‘ladi. Tokenning o‘zi har safar o‘zgaradi.
Yangi Go versiyalarida crypto/rand.Read() berilgan slice’ni to‘liq to‘ldiradi. Xato holatini tekshiradigan kod eski Go versiyalari bilan ham mos va chaqiruvning xavfsizlikka oid ekanini aniq ko‘rsatadi.
Modulo bias nima?
Tasodifiy baytni % n orqali kichik oraliqqa keltirish har doim bir xil taqsimot bermaydi. Masalan, bayt 0..255 oralig‘ida, n esa 10 bo‘lsa, ayrim qoldiqlar boshqalaridan ko‘proq uchraydi. Bu modulo og‘ishi (modulo bias) deyiladi.
crypto/rand.Int() mos kelmaydigan qiymatlarni tashlab, bir xil taqsimotni saqlaydi. Tasdiqlash kodi yoki xavfsiz indeks tanlashda undan foydalaning.
Qaysi paketni tanlash kerak?
| Vazifa | Paket | Sabab |
|---|---|---|
| Testni takrorlash | math/rand lokal generatori |
Bir xil seed bir xil oqim beradi |
| Simulyatsiya yoki o‘yin | math/rand |
Tez va qulay |
| Slice’ni xavfsizlikka aloqasiz aralashtirish | math/rand |
Shuffle() mavjud |
| Session ID yoki reset token | crypto/rand |
Natijani taxmin qilish qiyin |
| Kriptografik kalit | crypto/rand |
Xavfsiz tasodifiy baytlar beradi |
| Bir martalik tasdiqlash kodi | crypto/rand |
Bir xil taqsimot va taxmin qilishga chidamlilik kerak |
Keng tarqalgan xatolar
math/randni xavfsizlik tokeni uchun ishlatish. Seed yoki generator holati aniqlansa, keyingi qiymatlar taxmin qilinishi mumkin.- Har chaqiruv oldidan yangi vaqt seed’i yaratish. Tez ketma-ket chaqiruvlar bir xil yoki bog‘liq seed olishi mumkin. Bitta generatorni qayta ishlating.
Intn()yuqori chegarani ham qo‘shadi deb o‘ylash.Intn(10)faqat0..9qiymatlarini beradi.n <= 0holatini tekshirmaslik.Intn()vacrypto/rand.Int()noto‘g‘ri chegara bilan panic qiladi.- Tasodifiy natijaga aniq test yozish.
0 <= n && n < maxkabi invariantni tekshiring yoki lokal generatorga belgilangan seed bering.
Interviewda nimalarga e’tibor beriladi?
- Psevdotasodifiy va kriptografik xavfsiz generator o‘rtasidagi farq.
- Yarim ochiq
[0, n)oraliq vaIntn(n)ning panic sharti. - Takrorlanuvchi test uchun global
rand.Seed()emas, lokal*rand.Randishlatish. - Lokal
rand.Sourcening concurrent foydalanishga xavfsiz emasligi. % nbilan diapazonga keltirishdagi modulo bias.
Xulosa
math/rand simulyatsiya, o‘yin va takrorlanuvchi testlar uchun ishlatiladi. crypto/rand esa token, kalit va tasdiqlash kodi kabi xavfsizlikka oid qiymatlar uchun kerak. Chegaralarni tekshiring, [0, n) oraliqni hisobga oling va kriptografik qiymatlarni % n bilan yasamang.