feat(stringx): 自 go-hua/common 迁入字符串/切片/拼音工具并独立成包
- common 的 string.go/array.go/pinyin.go 拆为 stringx 包(含随机串、GUID、 通配符匹配、校验规则、链式缓冲、驼峰转下划线、切片删元素、拼音首字母) - 附单元测试与 examples/stringx 可运行例程、包 README - go.mod 新增直接依赖 mozillazg/go-pinyin(go-hua 同版本锁 v0.20.0→实际解析 v0.21.0)
This commit is contained in:
@@ -0,0 +1,257 @@
|
||||
// Package stringx 字符串与切片通用工具:随机串、UUID、通配符匹配、中间串提取、
|
||||
// 手机号/身份证校验、链式字节缓冲、驼峰转下划线、切片删元素、中文拼音首字母。
|
||||
package stringx
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// CreateRandomString 生成指定长度的随机字符串(含大小写字母与数字)
|
||||
func CreateRandomString(len int) string {
|
||||
var container string
|
||||
var str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
|
||||
b := bytes.NewBufferString(str)
|
||||
length := b.Len()
|
||||
bigInt := big.NewInt(int64(length))
|
||||
for i := 0; i < len; i++ {
|
||||
randomInt, _ := rand.Int(rand.Reader, bigInt)
|
||||
container += string(str[randomInt.Int64()])
|
||||
}
|
||||
return container
|
||||
}
|
||||
|
||||
// CreateRandomStringHex 生成指定长度的随机字符串(十六进制字符)
|
||||
func CreateRandomStringHex(len int) string {
|
||||
var container string
|
||||
var str = "ABCDEF1234567890"
|
||||
b := bytes.NewBufferString(str)
|
||||
length := b.Len()
|
||||
bigInt := big.NewInt(int64(length))
|
||||
for i := 0; i < len; i++ {
|
||||
randomInt, _ := rand.Int(rand.Reader, bigInt)
|
||||
container += string(str[randomInt.Int64()])
|
||||
}
|
||||
return container
|
||||
}
|
||||
|
||||
// CreateRandomStringInt 生成指定长度的纯数字随机字符串
|
||||
func CreateRandomStringInt(len int) string {
|
||||
var container string
|
||||
var str = "1234567890"
|
||||
b := bytes.NewBufferString(str)
|
||||
length := b.Len()
|
||||
bigInt := big.NewInt(int64(length))
|
||||
for i := 0; i < len; i++ {
|
||||
randomInt, _ := rand.Int(rand.Reader, bigInt)
|
||||
container += string(str[randomInt.Int64()])
|
||||
}
|
||||
return container
|
||||
}
|
||||
|
||||
// IsMatchDynamic 动态规划;时间复杂度O(n^2),空间复杂度O(n^2)
|
||||
func IsMatchDynamic(s string, p string) bool {
|
||||
n, m := len(s), len(p)
|
||||
dp := make([][]bool, n+1)
|
||||
for i := 0; i <= n; i++ {
|
||||
dp[i] = make([]bool, m+1)
|
||||
}
|
||||
dp[0][0] = true
|
||||
for i := 1; i <= m; i++ {
|
||||
if p[i-1] == '*' {
|
||||
// 可以匹配任意字符串(包括空字符串)
|
||||
dp[0][i] = true
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
for i := 1; i <= n; i++ {
|
||||
for j := 1; j <= m; j++ {
|
||||
if p[j-1] == '*' {
|
||||
// dp[i][j-1]=>不使用这个*,dp[i-1][j]=>使用这个*
|
||||
dp[i][j] = dp[i][j-1] || dp[i-1][j]
|
||||
} else if p[j-1] == '?' || s[i-1] == p[j-1] {
|
||||
dp[i][j] = dp[i-1][j-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[n][m]
|
||||
}
|
||||
|
||||
// IsMatchGreed 贪心;时间复杂度O(n^2),空间复杂度O(1)
|
||||
func IsMatchGreed(s string, p string) bool {
|
||||
i, j := 0, 0
|
||||
start, last := 0, 0
|
||||
for i = 0; i < len(s); {
|
||||
if j < len(p) && (s[i] == p[j] || p[j] == '?') {
|
||||
i++
|
||||
j++
|
||||
} else if j < len(p) && p[j] == '*' {
|
||||
last = i
|
||||
// 记录s下一个的位置
|
||||
start = j + 1
|
||||
// 记录*下一个的位置
|
||||
j++
|
||||
} else if start != 0 {
|
||||
last++
|
||||
i = last
|
||||
// 更新到s记录位置的下一个
|
||||
j = start
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for ; j < len(p) && p[j] == '*'; j++ {
|
||||
|
||||
}
|
||||
return j == len(p)
|
||||
}
|
||||
|
||||
// GetBetweenStr 取中间字符串
|
||||
func GetBetweenStr(str, starting, ending string) string {
|
||||
s := strings.Index(str, starting)
|
||||
if s < 0 {
|
||||
return ""
|
||||
}
|
||||
s += len(starting)
|
||||
if ending == "" {
|
||||
return str[s:]
|
||||
}
|
||||
e := strings.Index(str[s:], ending)
|
||||
|
||||
if e < 0 {
|
||||
return str[s:]
|
||||
}
|
||||
return str[s : s+e]
|
||||
}
|
||||
|
||||
// GetGUID 使用来自 crypto/rand 包的 rand.Read 函数来生成基本的 UUID。
|
||||
func GetGUID() string {
|
||||
b := make([]byte, 16)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
uuid := fmt.Sprintf("%x-%x-%x-%x-%x",
|
||||
b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
|
||||
return uuid
|
||||
}
|
||||
|
||||
// GetUUID 使用来自 crypto/rand 包的 rand.Read 函数来生成基本的 UUID。
|
||||
func GetUUID() string {
|
||||
b := make([]byte, 16)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
uuid := fmt.Sprintf("%x%x%x%x%x",
|
||||
b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
|
||||
return uuid
|
||||
}
|
||||
|
||||
// CheckMobile 检验手机号
|
||||
func CheckMobile(phone string) bool {
|
||||
// 匹配规则
|
||||
// ^1第一位为一
|
||||
// [345789]{1} 后接一位345789 的数字
|
||||
// \\d \d的转义 表示数字 {9} 接9位
|
||||
// $ 结束符
|
||||
regRuler := "^1[345789]{1}\\d{9}$"
|
||||
|
||||
// 正则调用规则
|
||||
reg := regexp.MustCompile(regRuler)
|
||||
|
||||
// 返回 MatchString 是否匹配
|
||||
return reg.MatchString(phone)
|
||||
}
|
||||
|
||||
// PhoneCheckRule 手机号验证规则
|
||||
func PhoneCheckRule() string {
|
||||
return "^1[3|4|5|6|7|8|9][0-9]\\d{8}$"
|
||||
}
|
||||
|
||||
// EmailCheckRule 邮箱验证规则
|
||||
func EmailCheckRule() string {
|
||||
return "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$"
|
||||
}
|
||||
|
||||
// CheckIdCard 检验身份证
|
||||
func CheckIdCard(card string) bool {
|
||||
//18位身份证 ^(\d{17})([0-9]|X)$
|
||||
// 匹配规则
|
||||
// (^\d{15}$) 15位身份证
|
||||
// (^\d{18}$) 18位身份证
|
||||
// (^\d{17}(\d|X|x)$) 18位身份证 最后一位为X的用户
|
||||
regRuler := "(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)"
|
||||
|
||||
// 正则调用规则
|
||||
reg := regexp.MustCompile(regRuler)
|
||||
|
||||
// 返回 MatchString 是否匹配
|
||||
return reg.MatchString(card)
|
||||
}
|
||||
|
||||
// Buffer 内嵌bytes.Buffer,支持连写
|
||||
type Buffer struct {
|
||||
*bytes.Buffer
|
||||
}
|
||||
|
||||
// NewBuffer 创建空字节缓冲
|
||||
func NewBuffer() *Buffer {
|
||||
return &Buffer{Buffer: new(bytes.Buffer)}
|
||||
}
|
||||
|
||||
// Append 追加任意类型数据并返回自身(支持链式调用)
|
||||
func (b *Buffer) Append(i interface{}) *Buffer {
|
||||
switch val := i.(type) {
|
||||
case int:
|
||||
b.append(strconv.Itoa(val))
|
||||
case int64:
|
||||
b.append(strconv.FormatInt(val, 10))
|
||||
case uint:
|
||||
b.append(strconv.FormatUint(uint64(val), 10))
|
||||
case uint64:
|
||||
b.append(strconv.FormatUint(val, 10))
|
||||
case string:
|
||||
b.append(val)
|
||||
case []byte:
|
||||
b.Write(val)
|
||||
case rune:
|
||||
b.WriteRune(val)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// append 追加字符串(容量不足时自动扩容)
|
||||
func (b *Buffer) append(s string) *Buffer {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
log.Println("*****内存不够了!******")
|
||||
}
|
||||
}()
|
||||
b.WriteString(s)
|
||||
return b
|
||||
}
|
||||
|
||||
// Camel2Case 驼峰式写法转为下划线写法
|
||||
func Camel2Case(name string) string {
|
||||
buffer := NewBuffer()
|
||||
for i, r := range name {
|
||||
if unicode.IsUpper(r) {
|
||||
if i != 0 {
|
||||
buffer.Append('_')
|
||||
}
|
||||
buffer.Append(unicode.ToLower(r))
|
||||
} else {
|
||||
buffer.Append(r)
|
||||
}
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
Reference in New Issue
Block a user