package common import ( "crypto/md5" cryptoRand "crypto/rand" "encoding/hex" "encoding/json" "encoding/xml" "fmt" "io" "log" "math" "math/big" mathRand "math/rand" "net/http" "reflect" "regexp" "runtime" "sort" "strconv" "strings" "time" date4 "app.yhyue.com/moapp/jybase/date" "github.com/dchest/captcha" ) const ( tmp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678900" ) func Uuid(length int) string { ret := []string{} r := mathRand.New(mathRand.NewSource(time.Now().UnixNano())) for i := 0; i < length; i++ { index := r.Intn(62) ret = append(ret, tmp[index:index+1]) } return strings.Join(ret, "") } //计算字符串和值 func Sumstring(code string) (sum int) { tmp := []rune(code) for _, v := range tmp { sum = sum + int(v) } return } //获取随机数 func GetRandom(n int) string { var idChars = []byte("0123456789") b := captcha.RandomDigits(n) for i, c := range b { b[i] = idChars[c] } return string(b) } //获取复杂的随机数 func GetLetterRandom(length int, flag ...bool) string { var idChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") var mod byte = 52 if len(flag) > 0 && flag[0] { idChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ") mod = 26 } b := make([]byte, length) maxrb := byte(256 - (256 % int(mod))) i := 0 EXIT: for { r := make([]byte, length+(length/4)) if _, err := io.ReadFull(cryptoRand.Reader, r); err != nil { panic("captcha: error reading random source: " + err.Error()) } for _, c := range r { if c > maxrb { continue } b[i] = c % mod i++ if i == length { break EXIT } } } for i, c := range b { b[i] = idChars[c] } return string(b) } /*获取复杂的随机数,数字和字母的组合 * c > 2 数字的个数和字母的个数随机分配 * n 数字的个数 * l 字母的个数 */ func GetComplexRandom(c, n, l int) string { if c < 2 && (n < 1 || l < 1) { return "--" } r := mathRand.New(mathRand.NewSource(time.Now().UnixNano())) myCommonMethod := func(flag bool) int { if flag { return r.Intn(c-1) + 1 } else { return r.Intn(c) } } if c >= 2 { n = myCommonMethod(true) l = c - n } else { c = l + n } value := GetRandom(n) + GetLetterRandom(l) var array = strings.Split(value, "") for i := 0; i < c/2; i++ { r1 := myCommonMethod(false) r2 := myCommonMethod(false) o := array[r1] array[r1] = array[r2] array[r2] = o } return strings.Join(array, "") } /*隐藏部分账号 *返回手机号:150...70765 邮箱:...shenjun@vip.qq.com */ func EncryCode(value string) string { if len(value) == 0 { return value } else if strings.Contains(value, "@") { start := strings.Index(value, "@") / 2 if start == 0 { start++ } value = "...." + string(value[start:]) } else { value = string(value[0:3]) + "..." + string(value[len(value)-4:]) } return value } //生成32位md5字串 func GetMd5String(s string) string { h := md5.New() h.Write([]byte(s)) return hex.EncodeToString(h.Sum(nil)) } //obj(string,M)转M,查询用到 func ObjToMap(obj interface{}) *map[string]interface{} { data := make(map[string]interface{}) if s, ok := obj.(string); ok { json.Unmarshal([]byte(strings.Replace(s, "'", "\"", -1)), &data) } else if s1, ok1 := obj.(map[string]interface{}); ok1 { data = s1 } else if s1, ok1 := obj.(*map[string]interface{}); ok1 { return s1 } else { data = nil } return &data } /*UTC类型时间转字符串 *flag==true,日期格式yyyy-mm-dd hh:mm:ss *flag==false,日期格式yyyy-mm-dd */ func LongToDate(date interface{}, flag bool) string { var int64Date int64 if l1, ok1 := date.(float64); ok1 { int64Date = int64(l1) } else if l2, ok2 := date.(int64); ok2 { int64Date = l2 } else if l3, ok3 := date.(int); ok3 { int64Date = int64(l3) } t := time.Unix(int64Date, 0) if flag { return t.Format("2006-01-02 15:04:05") } else { return t.Format("2006-01-02") } } func IntAll(num interface{}) int { return IntAllDef(num, 0) } func Int64All(num interface{}) int64 { if i, ok := num.(int64); ok { return int64(i) } else if i0, ok0 := num.(int32); ok0 { return int64(i0) } else if i1, ok1 := num.(float64); ok1 { return int64(i1) } else if i2, ok2 := num.(int); ok2 { return int64(i2) } else if i3, ok3 := num.(float32); ok3 { return int64(i3) } else if i4, ok4 := num.(string); ok4 { i64, _ := strconv.ParseInt(i4, 10, 64) //in, _ := strconv.Atoi(i4) return i64 } else if i5, ok5 := num.(int16); ok5 { return int64(i5) } else if i6, ok6 := num.(int8); ok6 { return int64(i6) } else if i7, ok7 := num.(*big.Int); ok7 { in, _ := strconv.ParseInt(fmt.Sprint(i7), 10, 64) return int64(in) } else if i8, ok8 := num.(*big.Float); ok8 { in, _ := strconv.ParseInt(fmt.Sprint(i8), 10, 64) return int64(in) } else { return 0 } } func Float64All(num interface{}) float64 { if i, ok := num.(float64); ok { return float64(i) } else if i0, ok0 := num.(int32); ok0 { return float64(i0) } else if i1, ok1 := num.(int64); ok1 { return float64(i1) } else if i2, ok2 := num.(int); ok2 { return float64(i2) } else if i3, ok3 := num.(float32); ok3 { return float64(i3) } else if i4, ok4 := num.(string); ok4 { in, _ := strconv.ParseFloat(i4, 64) return in } else if i5, ok5 := num.(int16); ok5 { return float64(i5) } else if i6, ok6 := num.(int8); ok6 { return float64(i6) } else if i6, ok6 := num.(uint); ok6 { return float64(i6) } else if i6, ok6 := num.(uint8); ok6 { return float64(i6) } else if i6, ok6 := num.(uint16); ok6 { return float64(i6) } else if i6, ok6 := num.(uint32); ok6 { return float64(i6) } else if i6, ok6 := num.(uint64); ok6 { return float64(i6) } else if i7, ok7 := num.(*big.Float); ok7 { in, _ := strconv.ParseFloat(fmt.Sprint(i7), 64) return float64(in) } else if i8, ok8 := num.(*big.Int); ok8 { in, _ := strconv.ParseFloat(fmt.Sprint(i8), 64) return float64(in) } else { return 0 } } func IntAllDef(num interface{}, defaultNum int) int { if i, ok := num.(int); ok { return int(i) } else if i0, ok0 := num.(int32); ok0 { return int(i0) } else if i1, ok1 := num.(float64); ok1 { return int(i1) } else if i2, ok2 := num.(int64); ok2 { return int(i2) } else if i3, ok3 := num.(float32); ok3 { return int(i3) } else if i4, ok4 := num.(string); ok4 { in, _ := strconv.Atoi(i4) return int(in) } else if i5, ok5 := num.(int16); ok5 { return int(i5) } else if i6, ok6 := num.(int8); ok6 { return int(i6) } else if i7, ok7 := num.(*big.Int); ok7 { in, _ := strconv.Atoi(fmt.Sprint(i7)) return int(in) } else if i8, ok8 := num.(*big.Float); ok8 { in, _ := strconv.Atoi(fmt.Sprint(i8)) return int(in) } else { return defaultNum } } func ObjToString(old interface{}) string { if nil == old { return "" } else { r, _ := old.(string) return r } } func ObjToStringDef(old interface{}, defaultstr string) string { if nil == old { return defaultstr } else { r, _ := old.(string) if r == "" { return defaultstr } return r } } //对象数组转成string数组 func ObjArrToStringArr(old []interface{}) []string { if old != nil { new := make([]string, len(old)) for i, v := range old { new[i], _ = v.(string) } return new } else { return nil } } //对象数组转成map数组 func ObjArrToMapArr(old []interface{}) []map[string]interface{} { if old != nil { new := make([]map[string]interface{}, len(old)) for i, v := range old { new[i], _ = v.(map[string]interface{}) } return new } else { return nil } } //map数组转成对象数组 func MapArrToObjArr(old []map[string]interface{}) []interface{} { if old != nil { new := make([]interface{}, len(old)) for i, v := range old { new[i] = v } return new } else { return nil } } func SubstrByByte(str string, length int) string { bs := []byte(str)[:length] bl := 0 for i := len(bs) - 1; i >= 0; i-- { switch { case bs[i] >= 0 && bs[i] <= 127: return string(bs[:i+1]) case bs[i] >= 128 && bs[i] <= 191: bl++ case bs[i] >= 192 && bs[i] <= 253: cl := 0 switch { case bs[i]&252 == 252: cl = 6 case bs[i]&248 == 248: cl = 5 case bs[i]&240 == 240: cl = 4 case bs[i]&224 == 224: cl = 3 default: cl = 2 } if bl+1 == cl { return string(bs[:i+cl]) } return string(bs[:i]) } } return "" } func SubString(str string, begin, length int) (substr string) { // 将字符串的转换成[]rune rs := []rune(str) lth := len(rs) // 简单的越界判断 if begin < 0 { begin = 0 } if begin >= lth { begin = lth } end := begin + length if end > lth { end = lth } // 返回子串 return string(rs[begin:end]) } //捕获异常 func Try(fun func(), handler func(interface{})) { defer func() { if err := recover(); err != nil { for skip := 1; ; skip++ { _, file, line, ok := runtime.Caller(skip) if !ok { break } go log.Printf("%v,%v\n", file, line) } handler(err) } }() fun() } //3目运算 func If(b bool, to, fo interface{}) interface{} { if b { return to } else { return fo } } //HashCode值 func HashCode(uid string) int { var h uint32 = 0 rs := []rune(uid) for i := 0; i < len(rs); i++ { h = 31*h + uint32(rs[i]) } return int(h) } //获取离n天的秒差 func GetDayStartSecond(n int) int64 { now := time.Now() tom := time.Date(now.Year(), now.Month(), now.Day()+n, 0, 0, 0, 0, time.Local) return tom.Unix() } func InterfaceArrTointArr(arr []interface{}) []int { tmp := make([]int, 0) for _, v := range arr { tmp = append(tmp, int(v.(float64))) } return tmp } func InterfaceArrToint64Arr(arr []interface{}) []int64 { tmp := make([]int64, 0) for _, v := range arr { tmp = append(tmp, int64(v.(float64))) } return tmp } func GetSubDay(t1 int64) int { tt1 := time.Unix(t1, 0) tt2 := time.Now() nt1 := time.Date(tt1.Year(), tt1.Month(), tt1.Day(), 0, 0, 0, 0, time.Local) nt2 := time.Date(tt2.Year(), tt2.Month(), tt2.Day(), 0, 0, 0, 0, time.Local) return int((nt1.Unix() - nt2.Unix()) / 86400) } func StartWith(value, str string) bool { ok, _ := regexp.MatchString("^"+str, value) return ok } func EndWith(value, str string) bool { ok, _ := regexp.MatchString(str+"$", value) return ok } //出错拦截 func Catch() { if r := recover(); r != nil { log.Println(r) for skip := 0; ; skip++ { _, file, line, ok := runtime.Caller(skip) if !ok { break } go log.Printf("%v,%v\n", file, line) } } } func ConvertFileSize(s int) string { size := float64(s) var kb float64 = 1024 var mb float64 = kb * 1024 var gb float64 = mb * 1024 if size >= gb { return fmt.Sprintf("%.1f GB", float64(size/gb)) } else if size >= mb { f := float64(size / mb) if f > 100 { return fmt.Sprintf("%.0f MB", f) } return fmt.Sprintf("%.1f MB", f) } else if size >= kb { f := float64(size / kb) if f > 100 { return fmt.Sprintf("%.0f KB", f) } return fmt.Sprintf("%.1f KB", f) } return fmt.Sprintf("%d B", s) } //MD5签名 func WxSign(format string, param ...interface{}) string { data := fmt.Sprintf(format, param...) h := md5.New() h.Write([]byte(data)) sign := strings.ToUpper(hex.EncodeToString(h.Sum(nil))) return sign } //计算时差 func TimeDiff(date time.Time) string { var date1 = date //开始时间 var date2 = time.Now() //结束时间 var date3 = date2.Unix() - date1.Unix() //时间差的毫秒数 //计算出相差天数 var days = math.Floor(float64(date3 / (24 * 3600))) //计算出小时数 var leave1 = date3 % (24 * 3600) //计算天数后剩余的毫秒数 var hours = math.Floor(float64(leave1 / (3600))) //计算相差分钟数 var leave2 = leave1 % (3600) //计算小时数后剩余的毫秒数 var minutes = math.Floor(float64(leave2 / (60))) //计算相差秒数 var td = "30秒前" if days > 0 { if days > 10 { if date1.Year() < date2.Year() { td = date4.FormatDate(&date, date4.Date_Short_Layout) } else { td = date4.FormatDate(&date, date4.Date_Small_Layout) } } else { td = fmt.Sprint(days) + "天前" } } else if hours > 0 { td = fmt.Sprint(hours) + "小时前" } else if minutes > 0 { td = fmt.Sprint(minutes) + "分钟前" } return td } func FloatFormat(tmp float64, n int) float64 { fs := fmt.Sprintf("%."+fmt.Sprint(n)+"f", tmp) f, _ := strconv.ParseFloat(fs, 64) return f } //生成微信支付的签名 func CreateWxSign(afterStr string, obj interface{}, filter ...string) string { filter = append(filter, "sign", "xml") keys := []string{} m := make(map[string]string) t := reflect.TypeOf(obj) v := reflect.ValueOf(obj) k := t.Kind() if t.Kind() == reflect.Ptr { t = t.Elem() k = t.Kind() v = v.Elem() } if k == reflect.Map { for _, key := range v.MapKeys() { keys = append(keys, key.String()) m[key.String()] = fmt.Sprint(v.MapIndex(key).Interface()) } } else if k == reflect.Struct { for n := 0; n < t.NumField(); n++ { tagName := t.Field(n).Tag.Get("xml") if tagName == "" { tagName = t.Field(n).Tag.Get("json") } if tagName == "" { tagName = t.Field(n).Name } keys = append(keys, tagName) m[tagName] = fmt.Sprint(v.Field(n)) } } sort.Strings(keys) vs := []string{} L: for _, v := range keys { for _, f := range filter { if f == v { continue L } } if strings.TrimSpace(m[v]) == "" { continue } vs = append(vs, fmt.Sprintf("%s=%s", v, m[v])) } return WxSign(strings.Join(vs, "&") + afterStr) } //简单的xml转map,只有一个层级,没有多层嵌套 func XmlToMap(input string) map[string]string { var t xml.Token var err error inputReader := strings.NewReader(input) decoder := xml.NewDecoder(inputReader) isStart := false nodeName := "" m := make(map[string]string) for t, err = decoder.Token(); err == nil; t, err = decoder.Token() { switch token := t.(type) { // 处理元素开始(标签) case xml.StartElement: isStart = true nodeName = token.Name.Local // 处理元素结束(标签) case xml.EndElement: isStart = false // 处理字符数据(这里就是元素的文本) case xml.CharData: if isStart { m[nodeName] = string([]byte(token)) } default: // ... } } return m } func SimpleCrontab(flag bool, c string, f func()) { array := strings.Split(c, ":") if len(array) != 2 { log.Fatalln("定时任务参数错误!", c) } if flag { go f() } now := time.Now() t := time.Date(now.Year(), now.Month(), now.Day(), IntAll(array[0]), IntAll(array[1]), 0, 0, time.Local) if t.Before(now) { t = t.AddDate(0, 0, 1) } sub := t.Sub(now) log.Println(c, "run after", sub) timer := time.NewTimer(sub) for { select { case <-timer.C: go f() log.Println(c, "run after", 24*time.Hour) timer.Reset(24 * time.Hour) } } } //v保留n为小数,n后的四舍五入 func RetainDecimal(v float64, n int) float64 { n10 := math.Pow10(n) return math.Trunc((v+0.5/n10)*n10) / n10 } //序列化成想要的类型,再断言 func JsonUnmarshal(m interface{}, s interface{}) interface{} { JsonUnmarshalByErr(m, s) return s } //序列化成想要的类型,再断言 func JsonUnmarshalByErr(m interface{}, s interface{}) (interface{}, error) { var b []byte var err error if v, ok := m.(string); ok { b = []byte(v) } else if v, ok := m.([]byte); ok { b = v } else { b, err = json.Marshal(m) } if err == nil { err = json.Unmarshal(b, &s) } return s, err } func MapToJson(param map[string]interface{}) string { if param == nil { return "" } dataType, _ := json.Marshal(param) dataString := string(dataType) return dataString } // 将string转换成map func StringToMap(str string) (jmap map[string]interface{}) { if err := json.Unmarshal([]byte(str), &jmap); err == nil { return } else { return } } // struct 转map func StructToMapMore(obj interface{}) map[string]interface{} { m := make(map[string]interface{}) j, _ := json.Marshal(obj) _ = json.Unmarshal(j, &m) return m } // 向上取整 func MathCeil(x float64) int { return int(math.Ceil(x + 0/5)) } // 向下取整 func MathFloor(x float64) int { return int(math.Floor(x + 0/5)) } // data 转换成ret func Bind(data interface{}, ret interface{}) error { v := reflect.ValueOf(ret) if v.Kind() != reflect.Ptr { return fmt.Errorf("ptr input ret needed as type as input type %s", v.Kind()) } havdata := false var bk interface{} if v.Elem().Kind() == reflect.Slice { t := reflect.Zero(reflect.TypeOf(v.Elem().Interface())) bk = v.Elem().Interface() v.Elem().Set(t) havdata = true } _data, _ := json.MarshalIndent(data, "", " ") err := json.Unmarshal(_data, ret) if err != nil { fmt.Println(err) if havdata { v.Elem().Set(reflect.ValueOf(bk)) } return err } return nil } //string func InterfaceToStr(x interface{}) string { switch st := reflect.ValueOf(x); st.Kind() { case reflect.Uint, reflect.Uintptr, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return strconv.FormatUint(uint64(st.Uint()), 10) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return strconv.FormatInt(int64(st.Int()), 10) case reflect.Float32, reflect.Float64: return strconv.FormatFloat(float64(st.Float()), 'g', -1, 64) case reflect.Bool: return strconv.FormatBool(st.Bool()) } var ret string _ = Bind(x, &ret) return ret } //StrFormat string追加格式化双引号 func StrFormat(s string) string { if s == "" { return "" } return fmt.Sprintf("\"%s\"", s) } //判断是否是微信访问 func IsWxBrowser(Request *http.Request) bool { if strings.Index(Request.UserAgent(), "MicroMessenger") > -1 || strings.Index(Request.UserAgent(), "Wechat") > -1 { return true } else { return false } } // func ShortenTxt(length int, fixed, shorten string) string { if len([]rune(fixed)) > length { return "" } else if len([]rune(fixed+shorten)) <= length { return shorten } if limit := length - len([]rune(fixed)) - 3; limit >= 0 && limit <= len([]rune(shorten)) { return string([]rune(shorten)[:limit]) + "..." } return "" }