From 34e7c5f809580598ac5a384e792ea7dabe936ba6 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 21 Feb 2020 00:01:27 +0800 Subject: [PATCH] rename grand.Str to grand.S; add different function Str for grand --- .example/other/test.go | 23 +++----------- os/gsession/gsession.go | 2 +- util/grand/grand.go | 54 +++++++++++++++++++++++++------- util/grand/grand_intn.go | 2 +- util/grand/grand_z_bench_test.go | 20 +++++++++++- util/grand/grand_z_unit_test.go | 31 ++++++++++++++++-- 6 files changed, 97 insertions(+), 35 deletions(-) diff --git a/.example/other/test.go b/.example/other/test.go index 1207f662d..8bf62b87b 100644 --- a/.example/other/test.go +++ b/.example/other/test.go @@ -2,25 +2,12 @@ package main import ( "fmt" - "github.com/gogf/gf/os/gtime" - "github.com/gogf/gf/util/gconv" + "github.com/gogf/gf/util/grand" ) func main() { - // select * from table1 where field1='1111' - // and ( - // (field2='2' and field3='3') - // or - // (field2='21' and field3='31') - // or - // (field2='22' and field3='32') - // ) - //g.DB().Table("table1"). - // Where("field1", "1111"). - // And(g.Map{"field2": 2, "field3": 3}) - //fmt.Println(gconv.GTime("2020-01-01 12:01:00").String()) - //t := gconv.Convert("2020-01-01 12:01:00", "gtime.Time").(gtime.Time) - t := gconv.Convert(1989, "gtime.Time").(gtime.Time) - fmt.Println(t.String()) - fmt.Println(gconv.String(t)) + s := "我爱GoFrame" + for i := 0; i <= 10; i++ { + fmt.Println(grand.Str(s, 10)) + } } diff --git a/os/gsession/gsession.go b/os/gsession/gsession.go index 9e544be5e..dee3bc254 100644 --- a/os/gsession/gsession.go +++ b/os/gsession/gsession.go @@ -23,5 +23,5 @@ var ( // NewSessionId creates and returns a new and unique session id string, // the length of which is 18 bytes. func NewSessionId() string { - return strings.ToUpper(strconv.FormatInt(gtime.TimestampNano(), 36) + grand.Str(6)) + return strings.ToUpper(strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6)) } diff --git a/util/grand/grand.go b/util/grand/grand.go index 4253c510c..5e622bed3 100644 --- a/util/grand/grand.go +++ b/util/grand/grand.go @@ -7,9 +7,15 @@ // Package grand provides high performance random string generation functionality. package grand +import ( + "unsafe" +) + var ( - letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") - digits = []rune("0123456789") + letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" // 52 + symbols = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" // 32 + digits = "0123456789" // 10 + characters = letters + digits + symbols // 94 ) // Meet randomly calculate whether the given probability / is met. @@ -22,7 +28,7 @@ func MeetProb(prob float32) bool { return Intn(1e7) < int(prob*1e7) } -// N returns a random int between min and max - [min, max]. +// N returns a random int between min and max: [min, max]. // The and also support negative numbers. func N(min, max int) int { if min >= max { @@ -45,31 +51,57 @@ func N(min, max int) int { return 0 } -// Str returns a random string which contains digits and letters, and its length is . -func Str(n int) string { - b := make([]rune, n) +// S returns a random string which contains digits and letters, and its length is . +// The optional parameter specifies whether the result could contain symbols, +// which is false in default. +func S(n int, symbols ...bool) string { + b := make([]byte, n) for i := range b { - b[i] = letters[Intn(62)] + if len(symbols) > 0 && symbols[0] { + b[i] = characters[Intn(94)] + } else { + b[i] = characters[Intn(62)] + } + } + return *(*string)(unsafe.Pointer(&b)) +} + +// Str randomly picks and returns count of chars from given string . +// It also supports unicode string like Chinese/Russian/Japanese, etc. +func Str(s string, n int) string { + b := make([]rune, n) + runes := []rune(s) + for i := range b { + b[i] = runes[Intn(len(runes))] } return string(b) } // Digits returns a random string which contains only digits, and its length is . func Digits(n int) string { - b := make([]rune, n) + b := make([]byte, n) for i := range b { b[i] = digits[Intn(10)] } - return string(b) + return *(*string)(unsafe.Pointer(&b)) } // Letters returns a random string which contains only letters, and its length is . func Letters(n int) string { - b := make([]rune, n) + b := make([]byte, n) for i := range b { b[i] = letters[Intn(52)] } - return string(b) + return *(*string)(unsafe.Pointer(&b)) +} + +// Symbols returns a random string which contains only symbols, and its length is . +func Symbols(n int) string { + b := make([]byte, n) + for i := range b { + b[i] = symbols[Intn(52)] + } + return *(*string)(unsafe.Pointer(&b)) } // Perm returns, as a slice of n int numbers, a pseudo-random permutation of the integers [0,n). diff --git a/util/grand/grand_intn.go b/util/grand/grand_intn.go index 22b312637..0b64e5637 100644 --- a/util/grand/grand_intn.go +++ b/util/grand/grand_intn.go @@ -36,7 +36,7 @@ func init() { bufferChan <- binary.LittleEndian.Uint32(buffer[i : i+4]) i++ } - // Reuse the rand buffers. + // Reuse the rand buffer. for i := 0; i < n; i++ { step = int(buffer[0]) % 10 if step != 0 { diff --git a/util/grand/grand_z_bench_test.go b/util/grand/grand_z_bench_test.go index f5363ac8c..10d21861f 100644 --- a/util/grand/grand_z_bench_test.go +++ b/util/grand/grand_z_bench_test.go @@ -18,12 +18,30 @@ import ( var buffer = make([]byte, 8) -func Benchmark_Rand(b *testing.B) { +func Benchmark_Rand1(b *testing.B) { + for i := 0; i < b.N; i++ { + grand.N(0, 99) + } +} + +func Benchmark_Rand2(b *testing.B) { for i := 0; i < b.N; i++ { grand.N(0, 999999999) } } +func Benchmark_Str(b *testing.B) { + for i := 0; i < b.N; i++ { + grand.S(16) + } +} + +func Benchmark_StrSymbols(b *testing.B) { + for i := 0; i < b.N; i++ { + grand.S(16, true) + } +} + func Benchmark_Buffer(b *testing.B) { for i := 0; i < b.N; i++ { if _, err := rand.Read(buffer); err == nil { diff --git a/util/grand/grand_z_unit_test.go b/util/grand/grand_z_unit_test.go index 70f34676f..340b9c57b 100644 --- a/util/grand/grand_z_unit_test.go +++ b/util/grand/grand_z_unit_test.go @@ -9,6 +9,7 @@ package grand_test import ( + "github.com/gogf/gf/text/gstr" "testing" "github.com/gogf/gf/test/gtest" @@ -92,15 +93,39 @@ func Test_Rand(t *testing.T) { func Test_Str(t *testing.T) { gtest.Case(t, func() { for i := 0; i < 100; i++ { - gtest.Assert(len(grand.Str(5)), 5) + gtest.Assert(len(grand.S(5)), 5) + } + }) +} + +func Test_RandS(t *testing.T) { + gtest.Case(t, func() { + for i := 0; i < 100; i++ { + gtest.Assert(len(grand.S(5)), 5) + } + }) + gtest.Case(t, func() { + for i := 0; i < 100; i++ { + gtest.Assert(len(grand.S(5, true)), 5) } }) } func Test_RandStr(t *testing.T) { + str := "我爱GoFrame" gtest.Case(t, func() { - for i := 0; i < 100; i++ { - gtest.Assert(len(grand.Str(5)), 5) + for i := 0; i < 10; i++ { + s := grand.Str(str, 100000) + gtest.Assert(gstr.Contains(s, "我"), true) + gtest.Assert(gstr.Contains(s, "爱"), true) + gtest.Assert(gstr.Contains(s, "G"), true) + gtest.Assert(gstr.Contains(s, "o"), true) + gtest.Assert(gstr.Contains(s, "F"), true) + gtest.Assert(gstr.Contains(s, "r"), true) + gtest.Assert(gstr.Contains(s, "a"), true) + gtest.Assert(gstr.Contains(s, "m"), true) + gtest.Assert(gstr.Contains(s, "e"), true) + gtest.Assert(gstr.Contains(s, "w"), false) } }) }