Files
exchange_go/pkg/utility/stringhelper.go
2025-02-06 11:14:33 +08:00

486 lines
10 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package utility
import (
"fmt"
"reflect"
"regexp"
"sort"
"strconv"
"strings"
"unicode/utf8"
"unsafe"
"go.uber.org/zap"
log "github.com/go-admin-team/go-admin-core/logger"
"github.com/shopspring/decimal"
)
// 获取不超过指定长度的字段
func StringCut(s string, maxLength int) string {
if len(s) > maxLength {
return s[:maxLength] // 获取前 maxLength 个字符
}
return s // 如果长度不足,返回原字符串
}
// FloatToStringZero 去掉多余的小数0,比如0.0245000返回0.0245,return string
func FloatToStringZero(num string) string {
de, _ := decimal.NewFromString(num)
str := de.String()
return str
}
// IntTostring int to string
func IntTostring(num int) string {
if num == 0 {
return "0"
}
return strconv.Itoa(num)
}
// StringLen 获取字符串真实长度
func StringLen(s string) int {
return len([]rune(s))
}
// StringIsNil 检测字符串长度是否为0
func StringIsNil(str string) bool {
if len(str) == 0 {
return true
}
return len(strings.Trim(str, " ")) == 0
}
// StringTrim 去前后空格
func StringTrim(str string) string {
return strings.Trim(str, " ")
}
// StringAsFloat tries to convert a string to float, and if it can't, just returns zero
// 尝试将字符串转换为浮点数如果不能则返回0
func StringAsFloat(s string) float64 {
if len(s) == 0 {
return 0.0
}
if f, err := strconv.ParseFloat(s, 64); err == nil {
return f
}
return 0.0
}
func StringAsDecimal(s string) decimal.Decimal {
if len(s) == 0 {
return decimal.Zero
}
f, err := decimal.NewFromString(s)
if err != nil {
log.Error("字符串转化decimal失败: ", zap.Error(err))
return decimal.Zero
}
return f
}
func StringAsFloatCut(s string, size int32) float64 {
if len(s) == 0 {
return 0
}
f, err := decimal.NewFromString(s)
if err != nil {
log.Error("字符串转化decimal失败: ", zap.Error(err))
return 0
}
d, _ := f.Truncate(size).Float64()
return d
}
// FloatToString 按保留的小数点位数,去掉多余的小数,return string
func FloatToString(num float64, size int32) string {
if num == 0 {
return getZero(size)
}
de := decimal.NewFromFloat(num)
str := de.Truncate(size).String()
return str
}
func getZero(size int32) string {
switch size {
case 0:
return "0"
case 1:
return "0.0"
case 2:
return "0.00"
case 3:
return "0.000"
case 4:
return "0.0000"
case 5:
return "0.00000"
case 6:
return "0.000000"
}
return "0"
}
func GetGearNumStr(size int32) string {
switch size {
case 0:
return "1"
case 1:
return "0.1"
case 2:
return "0.01"
case 3:
return "0.001"
case 4:
return "0.0001"
case 5:
return "0.00001"
case 6:
return "0.000001"
case 7:
return "0.0000001"
case 8:
return "0.00000001"
}
return "0.1"
}
func FloatToStr(num float64) string {
de := decimal.NewFromFloat(num)
str := de.String()
return str
}
// StringAsInteger returns the integer value extracted from string, or zero
func StringAsInteger(s string) int {
if s == "" {
return 0
}
if i, err := strconv.ParseInt(s, 10, 32); err == nil {
return int(i)
}
return 0
}
// StringAsInt64 returns the int64 value extracted from string, or zero
func StringAsInt64(s string) int64 {
if s == "" {
return 0
}
if i, err := strconv.ParseInt(s, 10, 64); err == nil {
return i
}
return 0
}
func StringAsInt32(s string) int32 {
if s == "" {
return 0
}
if i, err := strconv.ParseInt(s, 10, 64); err == nil {
return int32(i)
}
return 0
}
// StringToDecimal String To Decimal
func StringToDecimal(val string) decimal.Decimal {
cleanedNum := strings.TrimRight(val, "\x00") // 去除空字符
cleanedNum = strings.TrimSpace(cleanedNum) // 去除空格
cleanedNum = strings.ReplaceAll(cleanedNum, ",", "") // 去除逗号
d, err := decimal.NewFromString(cleanedNum)
if err != nil {
return decimal.Zero
}
return d
}
// StringToInt String => int
func StringToInt(val string) int {
i, err := strconv.Atoi(val)
if err != nil {
return 0
}
return i
}
// StringToFloat64 String => Float64
func StringToFloat64(val string) float64 {
d, err := strconv.ParseFloat(val, 64)
if err != nil {
return 0
}
return d
}
// ToLower 返回小写字符串
func ToLower(str string) string {
return strings.ToLower(str)
}
// ToUpper 返回大写字符串
func ToUpper(str string) string {
return strings.ToUpper(str)
}
// IntToString int to string
func IntToString(num int) string {
if num == 0 {
return "0"
}
return strconv.Itoa(num)
}
// CheckPhone returns true if a given sequence has between 9 and 14 digits
func CheckPhone(phone string, acceptEmpty bool) bool {
phone = OnlyDigits(phone)
return (acceptEmpty && (phone == "")) || ((len([]rune(phone)) >= 9) && (len([]rune(phone)) <= 14))
}
// OnlyDigits returns only the numbers from the given string, after strip all the rest ( letters, spaces, etc. )
func OnlyDigits(sequence string) string {
if utf8.RuneCountInString(sequence) > 0 {
re, _ := regexp.Compile(`[\D]`)
sequence = re.ReplaceAllString(sequence, "")
}
return sequence
}
// CheckEmail returns true if the given sequence is a valid email address
// See https://tools.ietf.org/html/rfc2822#section-3.4.1 for details about email address anatomy
func CheckEmail(email string) bool {
if email == "" {
return false
}
re := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
return re.MatchString(email)
}
// IsNumericType checks if an interface's concrete type corresponds to some of golang native numeric types
func IsNumericType(x interface{}) bool {
switch x.(type) {
case uint:
return true
case uint8: // Or byte
return true
case uint16:
return true
case uint32:
return true
case uint64:
return true
case int:
return true
case int8:
return true
case int16:
return true
case int32:
return true
case float32:
return true
case float64:
return true
case complex64:
return true
case complex128:
return true
default:
return false
}
}
// B2S converts byte slice to a string without memory allocation.
// See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ .
//
// Note it may break if string and/or slice header will change
// in the future go versions.
func B2S(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}
// S2B converts string to a byte slice without memory allocation.
// Note it may break if string and/or slice header will change
// in the future go versions.
func S2B(s string) (b []byte) {
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
sh := *(*reflect.StringHeader)(unsafe.Pointer(&s))
bh.Data = sh.Data
bh.Len = sh.Len
bh.Cap = sh.Len
return b
}
// Int64ToString int64 转到string
func Int64ToString(num int64) string {
if num == 0 {
return ""
}
return strconv.FormatInt(num, 10)
}
// Float64ToString Float64 转 string
// prec: 小数位数 -1 为全保留 与 FloatCutStr 不同的是 这里会四舍五入
func Float64ToString(num float64, prec int32) string {
return strconv.FormatFloat(num, 'f', int(prec), 64)
}
// SliceRemoveDuplicates 除去[]string数组重复的数据
func SliceRemoveDuplicates(slice []string) []string {
sort.Strings(slice)
i := 0
var j int
for {
if i >= len(slice)-1 {
break
}
for j = i + 1; j < len(slice) && slice[i] == slice[j]; j++ {
}
slice = append(slice[:i+1], slice[j:]...)
i++
}
return slice
}
func GetSymbolIdStr(coinId, currId string) string {
return fmt.Sprintf("%v/%v", coinId, currId)
}
func GetSymbolCoinIdAndCurrId(symbolIdStr string) (string, string) {
l := strings.Split(symbolIdStr, "/")
return l[0], l[1]
}
// 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)
}
func FilteredSQLInject(to_match_str string) bool {
//过滤
//ORACLE 注解 -- /**/
//关键字过滤 update ,delete
// 正则的字符串, 不能用 " " 因为" "里面的内容会转义
str := `(?:')|(?:--)|(/\*(?:.|[\n\r])*?\*/)|((select|update|and|or|delete|insert|trancate|char|chr|into|substr|ascii|declare|exec|count|master|into|drop|execute))`
re, err := regexp.Compile(str)
if err != nil {
return false
}
return re.MatchString(to_match_str)
}
func TrimHtml(src string) string {
//将HTML标签全转换成小写
re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
src = re.ReplaceAllStringFunc(src, strings.ToLower)
//去除STYLE
re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
src = re.ReplaceAllString(src, "")
//去除SCRIPT
re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
src = re.ReplaceAllString(src, "")
//去除所有尖括号内的HTML代码并换成换行符
re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
src = re.ReplaceAllString(src, "\n")
//去除连续的换行符
re, _ = regexp.Compile("\\s{2,}")
src = re.ReplaceAllString(src, "\n")
return strings.TrimSpace(src)
}
// ReplaceImages 过滤掉图片
func ReplaceImages(htmls string) string {
result := htmls
regx := `<img[^>]*src[="'s]+[^.]*/([^.]+).[^"']+["']?[^>]*>`
var imgRE = regexp.MustCompile(regx)
imgs := imgRE.FindAllStringSubmatch(htmls, -1)
for i := range imgs {
v := imgs[i]
result = strings.ReplaceAll(result, v[0], "")
}
return result
}
// KeySubString 文章搜索专用
func KeySubString(key, value string, leng int) string {
b := ReplaceImages(value)
pos := strings.Index(b, key)
if pos < 0 {
return ""
}
start := b[0:pos]
end := b[pos:]
out := Substr(end, leng)
return start + out
}
// Substr 截取字符串
func Substr(s string, l int) string {
if len(s) <= l {
return s
}
ss, sl, rl, rs := "", 0, 0, []rune(s)
for _, r := range rs {
rint := int(r)
if rint < 128 {
rl = 1
} else {
rl = 2
}
if sl+rl > l {
break
}
sl += rl
ss += string(r)
}
return ss
}
/*
根据字符串获取小数位数
*/
func GetPrecision(value string) int {
// 去掉末尾的多余零
value = strings.TrimRight(value, "0")
// 找到小数点的位置
decimalPos := strings.Index(value, ".")
if decimalPos == -1 {
// 如果没有小数点说明是整数精度为0
return 0
}
// 计算小数点后的位数
return len(value) - decimalPos - 1
}
// 替换字符串后缀
func ReplaceSuffix(text, oldSuffix, newSuffix string) string {
if strings.HasSuffix(text, oldSuffix) {
return text[:len(text)-len(oldSuffix)] + newSuffix
}
return text
}