-
Notifications
You must be signed in to change notification settings - Fork 164
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 优化slice的delete方法的性能 * 添加到ChangeLog中 * 新增生成随机code方法 * 修改changelog * randx:修改代码提升可读性提升 * randx:增加测试覆盖 * randx:测试修改为table driven方式 * randx:测试修改 --------- Signed-off-by: Zhang Cancan <[email protected]>
- Loading branch information
Showing
3 changed files
with
182 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// Copyright 2021 ecodeclub | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package randx | ||
|
||
import ( | ||
"errors" | ||
"math/rand" | ||
) | ||
|
||
var ERRTYPENOTSUPPORTTED = errors.New("ekit:不支持的类型") | ||
|
||
type TYPE int | ||
|
||
const ( | ||
TYPE_DEFAULT TYPE = 0 //默认类型 | ||
TYPE_DIGIT TYPE = 1 //数字// | ||
TYPE_LETTER TYPE = 2 //小写字母 | ||
TYPE_CAPITAL TYPE = 3 //大写字母 | ||
TYPE_MIXED TYPE = 4 //数字+字母混合 | ||
) | ||
|
||
// RandCode 根据传入的长度和类型生成随机字符串,这个方法目前可以生成数字、字母、数字+字母的随机字符串 | ||
func RandCode(length int, typ TYPE) (string, error) { | ||
switch typ { | ||
case TYPE_DEFAULT: | ||
fallthrough | ||
case TYPE_DIGIT: | ||
return generate("0123456789", length, 4), nil | ||
case TYPE_LETTER: | ||
return generate("abcdefghijklmnopqrstuvwxyz", length, 5), nil | ||
case TYPE_CAPITAL: | ||
return generate("ABCDEFGHIJKLMNOPQRSTUVWXYZ", length, 5), nil | ||
case TYPE_MIXED: | ||
return generate("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", length, 7), nil | ||
default: | ||
return "", ERRTYPENOTSUPPORTTED | ||
} | ||
} | ||
|
||
// generate 根据传入的随机源和长度生成随机字符串,一次随机,多次使用 | ||
func generate(source string, length, idxBits int) string { | ||
|
||
//掩码 | ||
//例如: 使用低6位:0000 0000 --> 0011 1111 | ||
idxMask := 1<<idxBits - 1 | ||
|
||
// 63位最多可以使用多少次 | ||
remain := 63 / idxBits | ||
|
||
//cache 随机位缓存 | ||
cache := rand.Int63() | ||
|
||
result := make([]byte, length) | ||
|
||
for i := 0; i < length; { | ||
//如果使用次数剩余0,重新获取随机 | ||
if remain == 0 { | ||
cache, remain = rand.Int63(), 63/idxBits | ||
} | ||
|
||
//利用掩码获取有效的随机数位 | ||
if randIndex := int(cache & int64(idxMask)); randIndex < len(source) { | ||
result[i] = source[randIndex] | ||
i++ | ||
} | ||
|
||
//使用下一组随机位 | ||
cache >>= idxBits | ||
|
||
//扣减remain | ||
remain-- | ||
|
||
} | ||
return string(result) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// Copyright 2021 ecodeclub | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package randx | ||
|
||
import ( | ||
"errors" | ||
"regexp" | ||
"testing" | ||
) | ||
|
||
func TestRandCode(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
length int | ||
typ TYPE | ||
wantMatch string | ||
wantErr error | ||
}{ | ||
{ | ||
name: "默认类型", | ||
length: 8, | ||
typ: TYPE_DEFAULT, | ||
wantMatch: "^[0-9]+$", | ||
wantErr: nil, | ||
}, | ||
{ | ||
name: "数字验证码", | ||
length: 8, | ||
typ: TYPE_DIGIT, | ||
wantMatch: "^[0-9]+$", | ||
wantErr: nil, | ||
}, { | ||
name: "小写字母验证码", | ||
length: 8, | ||
typ: TYPE_LETTER, | ||
wantMatch: "^[a-z]+$", | ||
wantErr: nil, | ||
}, { | ||
name: "大写字母验证码", | ||
length: 8, | ||
typ: TYPE_CAPITAL, | ||
wantMatch: "^[A-Z]+$", | ||
wantErr: nil, | ||
}, { | ||
name: "混合验证码", | ||
length: 8, | ||
typ: TYPE_MIXED, | ||
wantMatch: "^[0-9a-zA-Z]+$", | ||
wantErr: nil, | ||
}, { | ||
name: "未定义类型", | ||
length: 8, | ||
typ: 9, | ||
wantMatch: "", | ||
wantErr: ERRTYPENOTSUPPORTTED, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
code, err := RandCode(tc.length, tc.typ) | ||
if err != nil { | ||
if !errors.Is(err, tc.wantErr) { | ||
t.Errorf("unexpected error: %v", err) | ||
} | ||
} else { | ||
//长度检验 | ||
if len(code) != tc.length { | ||
t.Errorf("expected length: %d but got length:%d ", tc.length, len(code)) | ||
} | ||
//模式检验 | ||
matched, _ := regexp.MatchString(tc.wantMatch, code) | ||
if !matched { | ||
t.Errorf("expected %s but got %s", tc.wantMatch, code) | ||
} | ||
} | ||
}) | ||
} | ||
|
||
} |