255 lines
5.5 KiB
Go
255 lines
5.5 KiB
Go
package goutil
|
||
|
||
import (
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
"math/rand"
|
||
"reflect"
|
||
"regexp"
|
||
"sort"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
// FormatMoney 格式化商品价格
|
||
func FormatMoney(number int64) string {
|
||
num1 := float64(number) / 100
|
||
num2 := float64(number / 100)
|
||
if num1 != num2 {
|
||
return fmt.Sprintf("%.2f", num1)
|
||
}
|
||
return strconv.FormatInt(int64(num1), 10)
|
||
}
|
||
|
||
func FormatFloat(f float64) string {
|
||
if int64(f*100)%100 == 0 {
|
||
return fmt.Sprintf("%d", int64(f))
|
||
}
|
||
return fmt.Sprintf("%.2f", f)
|
||
}
|
||
|
||
func FormatPercent(number float64) string {
|
||
if number*100 == float64(int(number*100)) {
|
||
return fmt.Sprintf("%d%%", int(number*100))
|
||
}
|
||
val := strings.TrimRight(fmt.Sprintf("%.2f", number*100), "0.")
|
||
return val + "%"
|
||
}
|
||
|
||
func FormatBytes(bytes int64) string {
|
||
const unit = 1024
|
||
if bytes < unit {
|
||
return strconv.FormatInt(bytes, 10) + " B"
|
||
}
|
||
div, exp := int64(unit), 0
|
||
for n := bytes / unit; n >= unit; n /= unit {
|
||
div *= unit
|
||
exp++
|
||
}
|
||
return fmt.Sprintf("%.2f%cB", float64(bytes)/float64(div), "KMGTPE"[exp])
|
||
}
|
||
|
||
// FormatNumber 格式化整数为千分位显示,支持正负数
|
||
func FormatNumber(num int64) string {
|
||
// 处理符号
|
||
sign := ""
|
||
if num < 0 {
|
||
sign = "-"
|
||
num = -num
|
||
}
|
||
|
||
// 转换为字符串处理
|
||
str := fmt.Sprintf("%d", num)
|
||
length := len(str)
|
||
|
||
// 小于等于3位直接返回
|
||
if length <= 3 {
|
||
return sign + str
|
||
}
|
||
|
||
// 计算第一个逗号位置
|
||
firstComma := length % 3
|
||
if firstComma == 0 {
|
||
firstComma = 3
|
||
}
|
||
|
||
// 构建格式化字符串
|
||
var builder strings.Builder
|
||
builder.WriteString(str[:firstComma])
|
||
|
||
for i := firstComma; i < length; i += 3 {
|
||
builder.WriteString(",")
|
||
builder.WriteString(str[i : i+3])
|
||
}
|
||
|
||
return sign + builder.String()
|
||
}
|
||
|
||
func If[T any](condition bool, trueVal, falseVal T) T {
|
||
if condition {
|
||
return trueVal
|
||
}
|
||
return falseVal
|
||
}
|
||
|
||
func CopyStruct(dst interface{}, src interface{}) {
|
||
|
||
dtype := reflect.TypeOf(dst)
|
||
stype := reflect.TypeOf(src)
|
||
|
||
if stype.Kind() != reflect.Ptr || stype.Kind() != dtype.Kind() {
|
||
panic(errors.New("src/dst must ptr"))
|
||
}
|
||
if reflect.ValueOf(dst).IsNil() || reflect.ValueOf(src).IsNil() {
|
||
panic(errors.New("src/dst is nil"))
|
||
}
|
||
|
||
dval := reflect.ValueOf(dst).Elem()
|
||
sval := reflect.ValueOf(src).Elem()
|
||
|
||
for i := 0; i < sval.NumField(); i++ {
|
||
sValue := sval.Field(i)
|
||
|
||
dValue := dval.FieldByName(sval.Type().Field(i).Name)
|
||
if sValue.IsZero() || dValue.IsValid() == false || !dValue.CanSet() {
|
||
continue
|
||
}
|
||
if sValue.Kind() != dValue.Kind() {
|
||
continue
|
||
}
|
||
|
||
switch sValue.Type().Kind() {
|
||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
dValue.SetInt(sValue.Int())
|
||
|
||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||
dValue.SetUint(sValue.Uint())
|
||
|
||
case reflect.Float32, reflect.Float64:
|
||
dValue.SetFloat(sValue.Float())
|
||
|
||
case reflect.String:
|
||
dValue.SetString(sValue.String())
|
||
|
||
case reflect.Bool:
|
||
dValue.SetBool(sValue.Bool())
|
||
|
||
case reflect.Ptr:
|
||
CopyStruct(dValue.Interface(), sValue.Interface())
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
func HtmlStrip(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, "")
|
||
|
||
//去除连续的换行符
|
||
re, _ = regexp.Compile("\\s{1,}")
|
||
src = re.ReplaceAllString(src, "")
|
||
|
||
//去除〹这类字符
|
||
//re, _ = regexp.Compile("&#\\d*;")
|
||
//src = re.ReplaceAllString(src, "")
|
||
|
||
src = strings.ReplaceAll(src, " ", "")
|
||
src = strings.ReplaceAll(src, "nbsp;", "")
|
||
src = strings.ReplaceAll(src, "& nbsp;", "")
|
||
src = strings.ReplaceAll(src, " ", "")
|
||
return strings.TrimSpace(src)
|
||
}
|
||
|
||
func Reverse(s interface{}) {
|
||
sort.SliceStable(s, func(i, j int) bool {
|
||
return true
|
||
})
|
||
}
|
||
|
||
func WeightKeyword(keywords string) string {
|
||
fields := strings.Split(keywords, ",")
|
||
if len(fields) == 1 {
|
||
return keywords
|
||
}
|
||
|
||
sumWeight := int(0)
|
||
arrWeight := make([]int, 0)
|
||
arrKey := make([]string, 0)
|
||
zeroWeightKey := make([]string, 0)
|
||
|
||
for _, field := range fields {
|
||
field = strings.Trim(field, "\r\t\n ")
|
||
kvs := strings.SplitN(field, ":", 2)
|
||
key := strings.Trim(kvs[0], "\r\t\n ")
|
||
weight := int(0)
|
||
if len(kvs) > 1 {
|
||
weight, _ = strconv.Atoi(strings.Trim(kvs[1], "\r\t\n "))
|
||
}
|
||
|
||
if weight <= 0 {
|
||
zeroWeightKey = append(zeroWeightKey, key)
|
||
continue
|
||
}
|
||
sumWeight += weight
|
||
arrWeight = append(arrWeight, sumWeight)
|
||
arrKey = append(arrKey, key)
|
||
}
|
||
if sumWeight == 0 && len(zeroWeightKey) > 0 {
|
||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||
return zeroWeightKey[r.Intn(len(zeroWeightKey))]
|
||
}
|
||
|
||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||
randWeight := r.Intn(sumWeight)
|
||
|
||
for i := 0; i < len(arrWeight); i++ {
|
||
if randWeight < arrWeight[i] {
|
||
return arrKey[i]
|
||
}
|
||
}
|
||
|
||
return ""
|
||
}
|
||
|
||
func MergeMap(m1, m2 string) string {
|
||
var c1 map[string]interface{}
|
||
var c2 map[string]interface{}
|
||
|
||
if strings.TrimSpace(m1) == "" {
|
||
return m2
|
||
}
|
||
if strings.TrimSpace(m2) == "" {
|
||
return m1
|
||
}
|
||
json.Unmarshal([]byte(m1), &c1)
|
||
json.Unmarshal([]byte(m2), &c2)
|
||
if c1 == nil {
|
||
c1 = make(map[string]interface{})
|
||
}
|
||
if c2 == nil {
|
||
c2 = make(map[string]interface{})
|
||
}
|
||
|
||
for k, v := range c2 {
|
||
c1[k] = v
|
||
}
|
||
|
||
res, _ := json.Marshal(c1)
|
||
return string(res)
|
||
}
|