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("\\") src = re.ReplaceAllString(src, "") //去除SCRIPT re, _ = regexp.Compile("\\") 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 := `]*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 }