package tool import ( "bufio" "bytes" "errors" "fmt" "io" "math" "math/rand" "net" "net/http" "net/url" "os" "regexp" "strconv" "strings" "time" "unicode" ) // GetOrderNumber 获取订单号 func GetOrderNumber() string { parse, _ := time.Parse(time.DateTime, "2021-04-27 00:00:00") hours := time.Now().Sub(parse).Hours() day := math.Floor(hours / 24) prefix := fmt.Sprintf("%05d", int64(day)) format := time.Now().Format("") + "%0" + strconv.Itoa(10) + "d" n := math.Pow10(10) return prefix + fmt.Sprintf(format, rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(int64(n))) } // ByteFmt 格式化显示文件大小 func ByteFmt(size int64) string { var unitArr = []string{"B", "KB", "MB", "GB", "TB", "EB"} if size == 0 { return "unknown" } fs := float64(size) p := int(math.Log(fs) / math.Log(1024)) val := fs / math.Pow(1024, float64(p)) _, frac := math.Modf(val) if frac > 0 { return fmt.Sprintf("%.1f%s", math.Floor(val*10)/10, unitArr[p]) } else { return fmt.Sprintf("%d%s", int(val), unitArr[p]) } } // UniqueArray 切片唯一值 func UniqueArray[T comparable](array []T) []T { result := make([]T, 0, len(array)) temp := map[T]struct{}{} for _, item := range array { if _, ok := temp[item]; !ok { temp[item] = struct{}{} result = append(result, item) } } return result } // InArray 是否在切片 func InArray[T comparable](item T, array []T) bool { for _, s := range array { if item == s { return true } } return false } // IsChinese 判断字符串是否包含中文 func IsChinese(str string) bool { var count int for _, v := range str { if unicode.Is(unicode.Han, v) { count++ break } } return count > 0 } // RandInt 随机数 func RandInt(max int) int { if max <= 0 { return 0 } return rand.Intn(max) } // FindIPv4 字符串中查找IP4 func FindIPv4(input string) string { partIp := "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])" must := partIp + "\\." + partIp + "\\." + partIp + "\\." + partIp matchMe := regexp.MustCompile(must) return matchMe.FindString(input) } // RandString 随机字符串 func RandString(n int) string { var letterRunes = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") b := make([]rune, n) for i := range b { b[i] = letterRunes[RandInt(len(letterRunes))] } return string(b) } // IP4ToInt ip4地址转Int类型 func IP4ToInt(ip net.IP) int { ipSplit := strings.Split(ip.To4().String(), ".") var ipInt = 0 var pos uint = 24 for _, ipSeg := range ipSplit { tempInt, _ := strconv.Atoi(ipSeg) tempInt = tempInt << pos ipInt = ipInt | tempInt pos -= 8 } return ipInt } // IP4IntToString 反序列化Int为IP4地址 func IP4IntToString(ipInt int) string { ipSplit := make([]string, 4) var length = len(ipSplit) buffer := bytes.NewBufferString("") for i := 0; i < length; i++ { tempInt := ipInt & 0xFF ipSplit[length-i-1] = strconv.Itoa(tempInt) ipInt = ipInt >> 8 } for i := 0; i < length; i++ { buffer.WriteString(ipSplit[i]) if i < length-1 { buffer.WriteString(".") } } return buffer.String() } // CompareVersion 比较`x.y.z`类型版本号大小 func CompareVersion(verCurrent, verUpdate string) int { versionA := strings.Split(verCurrent, ".") versionB := strings.Split(verUpdate, ".") for i := len(versionA); i < 4; i++ { versionA = append(versionA, "0") } for i := len(versionB); i < 4; i++ { versionB = append(versionB, "0") } for i := 0; i < 4; i++ { version1, _ := strconv.Atoi(versionA[i]) version2, _ := strconv.Atoi(versionB[i]) if version1 == version2 { continue } else if version1 > version2 { return 1 } else { return -1 } } return 0 } // GetLocalIP 获取内网本机ipv4地址 func GetLocalIP() (string, error) { var address []net.Addr eth0Interface, err := net.InterfaceByName("eth0") if err == nil { address, err = eth0Interface.Addrs() } else { address, err = net.InterfaceAddrs() } if err != nil { return "", err } for _, addr := range address { if it, ok := addr.(*net.IPNet); ok && !it.IP.IsLoopback() { if it.IP.To4() != nil { return it.IP.String(), nil } } } return "", err } // GetInternetIP 获取外网本机ipv4地址 func GetInternetIP() (string, error) { resp, err := http.Get("https://api.ipify.org") if err != nil { resp, err = http.Get("https://icanhazip.com") if err != nil { return "", err } } defer func() { _ = resp.Body.Close() }() s, readErr := io.ReadAll(resp.Body) if readErr != nil { return "", readErr } return string(s), nil } // IsExists 检测指定路径文件或者文件夹是否存在 func IsExists(path string) bool { _, err := os.Stat(path) //os.Stat获取文件信息 if err != nil { if os.IsExist(err) { return true } return false } return true } // CheckWebsiteAddr 检查域名是否正确 func CheckWebsiteAddr(addr string) error { if 0 == len(addr) { return errors.New("url is empty") } parse, err := url.Parse(addr) if err != nil { return err } if "http" != parse.Scheme && "https" != parse.Scheme { return errors.New("url Scheme illegal. err:" + parse.Scheme) } re := regexp.MustCompile(`^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)+([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$`) u := strings.Split(parse.Host, ":") if 2 == len(u) && 0 != len(u[1]) { result := re.FindAllStringSubmatch(u[0], -1) if result == nil { return errors.New("url illegal. err:" + u[0]) } return nil } result := re.FindAllStringSubmatch(parse.Host, -1) if result == nil { return errors.New("url illegal. err:" + parse.Host) } return nil } // LoadKeyValConfig 获取本地`a=c\n`类型文件的键值对 func LoadKeyValConfig(text string) map[string]string { config := make(map[string]string) r := bufio.NewReader(bytes.NewBufferString(text)) for { b, _, err := r.ReadLine() if err != nil { if err == io.EOF { break } panic(err) } s := strings.TrimSpace(string(b)) index := strings.Index(s, "=") if index < 0 || strings.HasPrefix(s, "#") { continue } key := strings.TrimSpace(s[:index]) if len(key) == 0 { continue } value := strings.TrimSpace(s[index+1:]) if len(value) == 0 { continue } config[key] = value } return config } // PortIsUse 判断端口是否占用 func PortIsUse(port int) bool { _, tcpError := net.DialTimeout("tcp", fmt.Sprintf(":%d", port), time.Millisecond*50) udpAddr, _ := net.ResolveUDPAddr("udp4", fmt.Sprintf(":%d", port)) udpConn, udpError := net.ListenUDP("udp", udpAddr) if udpConn != nil { defer func() { _ = udpConn.Close() }() } return tcpError == nil || udpError != nil }