package global import ( "archive/zip" "bytes" "crypto/md5" "encoding/hex" "encoding/json" "fmt" "io" "net" "net/http" "os" "path/filepath" "reflect" "regexp" "sort" "strings" "time" ) const ( IsIPv4 = "IPv4" IsIPv6 = "IPv6" NonIP = "NonIp" ) type em struct{} func GetPkgName() string { return reflect.TypeOf(em{}).PkgPath() } // interface{} change to map[string]interface{} // interface{} data is []interface{} func ListToMap(list interface{}, key string) map[string]interface{} { res := make(map[string]interface{}) arr := ToSlice(list) for _, row := range arr { immutable := reflect.ValueOf(row) val := immutable.FieldByName(key).String() res[val] = row } return res } // interface{} change to []interface{} func ToSlice(arr interface{}) []interface{} { ret := make([]interface{}, 0) v := reflect.ValueOf(arr) if v.Kind() != reflect.Slice { ret = append(ret, arr) return ret } l := v.Len() for i := 0; i < l; i++ { ret = append(ret, v.Index(i).Interface()) } return ret } var TodoList []Todo type Todo struct { Id int64 Item string } // JSON序列化方式 func jsonStructToMap(TodoList Todo) (map[string]interface{}, error) { // 结构体转json strRet, err := json.Marshal(TodoList) if err != nil { return nil, err } // json转map var mRet map[string]interface{} err1 := json.Unmarshal(strRet, &mRet) if err1 != nil { return nil, err1 } return mRet, nil } func IsContain(item string, items []string) bool { for _, e := range items { if e == item { return true } } return false } func IsContainP(item string, items *[]string, size int) bool { for i := 0; i < size; i++ { if (*items)[i] == item { return true } } return false } // 将字符串 分割成 字符串数组 // @s:分割符 func SplitString(str string, s string) []string { sa := strings.Split(str, s) return sa } //  合并字符串数组 func MergeStringArr(a, b []string) []string { var arr []string for _, i := range a { arr = append(arr, i) } for _, j := range b { arr = append(arr, j) } return arr } // 数组去重 func UniqueStringArr(m []string) []string { d := make([]string, 0) tempMap := make(map[string]bool, len(m)) for _, v := range m { // 以值作为键名 if tempMap[v] == false { tempMap[v] = true d = append(d, v) } } return d } //  合并整型数组 func MergeArr(a, b []int) []int { var arr []int for _, i := range a { arr = append(arr, i) } for _, j := range b { arr = append(arr, j) } return arr } // 数组去重 func UniqueArr(m []int) []int { d := make([]int, 0) tempMap := make(map[int]bool, len(m)) for _, v := range m { // 以值作为键名 if tempMap[v] == false { tempMap[v] = true d = append(d, v) } } return d } // 升序 func AscArr(e []int) []int { sort.Ints(e[:]) return e } // 降序 func DescArr(e []int) []int { sort.Sort(sort.Reverse(sort.IntSlice(e))) return e } func MatchRmUID(p string, s string) bool { match, _ := regexp.MatchString(p, s) return match } type OrderedMap struct { Order []string Map map[string]interface{} } func (om *OrderedMap) UnmarshalJson(b []byte) error { json.Unmarshal(b, &om.Map) index := make(map[string]int) for key := range om.Map { om.Order = append(om.Order, key) esc, _ := json.Marshal(key) //Escape the key index[key] = bytes.Index(b, esc) } sort.Slice(om.Order, func(i, j int) bool { return index[om.Order[i]] < index[om.Order[j]] }) return nil } func (om OrderedMap) MarshalJson() ([]byte, error) { var b []byte buf := bytes.NewBuffer(b) buf.WriteRune('{') l := len(om.Order) for i, key := range om.Order { km, err := json.Marshal(key) if err != nil { return nil, err } buf.Write(km) buf.WriteRune(':') vm, err := json.Marshal(om.Map[key]) if err != nil { return nil, err } buf.Write(vm) if i != l-1 { buf.WriteRune(',') } fmt.Println(buf.String()) } buf.WriteRune('}') fmt.Println(buf.String()) return buf.Bytes(), nil } func GetBodyCopy(r *http.Request) (*bytes.Buffer, error) { // If r.bodyBuf present, return the copy // if r.bodyBuf != nil { // return bytes.NewBuffer(r.bodyBuf.Bytes()), nil // } // Maybe body is `io.Reader`. // Note: Resty user have to watchout for large body size of `io.Reader` if r.Body != nil { b, err := io.ReadAll(r.Body) if err != nil { return nil, err } // Restore the Body // close(r.Body) r.Body = io.NopCloser(bytes.NewReader(b)) // Return the Body bytes return bytes.NewBuffer(b), nil } return nil, nil } func UnmarshalBody(r *http.Request, v *interface{}, maxLen int64) error { body, err := io.ReadAll(io.LimitReader(r.Body, maxLen)) if err != nil { return err } return json.Unmarshal(body, v) } func SetNotifyUrl(ip string, port uint16, uri string) string { return fmt.Sprintf("http://%s:%d%s", ip, port, uri) } func GetIps() (ips []string, err error) { interfaceAddr, err := net.InterfaceAddrs() if err != nil { return ips, err } for _, address := range interfaceAddr { ipNet, isVailIpNet := address.(*net.IPNet) // 检查ip地址判断是否回环地址 if isVailIpNet && !ipNet.IP.IsLoopback() { if ipNet.IP.To4() != nil { ips = append(ips, ipNet.IP.String()) } } } return ips, nil } func GetCurrentTimeSliceIndexByPeriod(t time.Time, period int) int { index := int((t.Hour()*60+t.Minute())/period) - 1 if index < 0 { return int(24*60/period) - 1 } return index } var ( cst *time.Location ) // RFC3339ToDateTime convert rfc3339 value to china standard time layout func RFC3339ToDateTime(value string) (string, error) { ts, err := time.Parse(time.RFC3339, value) if err != nil { return "", err } return ts.In(cst).Format("2006-01-02 15:04:05"), nil } // CreateTimeDir 根据当前时间格式来创建文件夹 func CreateTimeDir(fmt string, path string) string { folderName := time.Now().Format(fmt) folderPath := filepath.Join(path, folderName) if _, err := os.Stat(folderPath); os.IsNotExist(err) { // 必须分成两步:先创建文件夹、再修改权限 os.Mkdir(folderPath, 0664) //0644也可以os.ModePerm os.Chmod(folderPath, 0664) } return folderPath } // CreateDir 根据传入的目录名和路径来创建文件夹 func CreateDir(folderName string, path string) string { folderPath := filepath.Join(path, folderName) if _, err := os.Stat(folderPath); os.IsNotExist(err) { // 必须分成两步:先创建文件夹、再修改权限 os.MkdirAll(folderPath, 0664) //0644也可以os.ModePerm os.Chmod(folderPath, 0664) } return folderPath } func GetFmtTimeString(srcFmt string, timeString string, dstFmt string) string { t, _ := time.ParseInLocation(srcFmt, timeString, time.Local) return t.Format(dstFmt) } func GetFileMD5Sum(filePath string) (string, error) { file, err := os.Open(filePath) if err != nil { return "", err } defer file.Close() md5 := md5.New() _, err = io.Copy(md5, file) if err != nil { return "", err } md5str := hex.EncodeToString(md5.Sum(nil)) return md5str, nil } // PathExists check path is exist or no func PathExists(path string) (bool, error) { _, err := os.Stat(path) if err == nil { //文件或者目录存在 return true, nil } if os.IsNotExist(err) { return false, nil } return false, err } // PathExists check path is exist or no func FilePathExists(filePath string) (bool, error) { _, err := os.Stat(filePath) if err == nil { //文件或者目录存在 return true, nil } if os.IsNotExist(err) { return false, nil } return false, err } func GetDayDuration(d1, d2 string) int64 { a, _ := time.Parse("2006-01-02", d1) b, _ := time.Parse("2006-01-02", d2) d := a.Sub(b) return (int64)(d.Hours() / 24) } func GetSecondsSinceDatetime(datetimeStr string) (int64, error) { loc1, _ := time.LoadLocation("Local") // 解析日期时间字符串为时间对象 datetime, err := time.ParseInLocation(time.DateTime, datetimeStr, loc1) if err != nil { return 0, err } // 计算时间差 duration := time.Since(datetime) // 获取时间差的秒数 seconds := int64(duration.Seconds()) return seconds, nil } // 0: invalid ip // 4: IPv4 // 6: IPv6 func ParseIP(s string) (net.IP, int) { ip := net.ParseIP(s) if ip == nil { return nil, 0 } for i := 0; i < len(s); i++ { switch s[i] { case '.': return ip, 4 case ':': return ip, 6 } } return nil, 0 } func BytesCombine1(pBytes ...[]byte) []byte { return bytes.Join(pBytes, []byte("")) } func BytesCombine(pBytes ...[]byte) []byte { length := len(pBytes) s := make([][]byte, length) for index := 0; index < length; index++ { s[index] = pBytes[index] } sep := []byte("") return bytes.Join(s, sep) } func ParseIPAddr(ip string) string { ipAddr := net.ParseIP(ip) if ipAddr != nil { if ipAddr.To4() != nil { return IsIPv4 } else { return IsIPv6 } } return NonIP } func CombineHostUri(ip string, port string) string { var hostUri string = "" ipType := ParseIPAddr(ip) if ipType == IsIPv4 { hostUri = fmt.Sprintf("http://%s:%v", ip, port) } else { hostUri = fmt.Sprintf("http://[%s]:%v", ip, port) } return hostUri } func StructToMap(obj interface{}) map[string]interface{} { objValue := reflect.ValueOf(obj) objType := objValue.Type() m := make(map[string]interface{}) for i := 0; i < objValue.NumField(); i++ { field := objValue.Field(i) fieldName := objType.Field(i).Name m[fieldName] = field.Interface() } return m } // ToMap 结构体转为Map[string]interface{} func ToMap(in interface{}, tagName string) (map[string]interface{}, error) { out := make(map[string]interface{}) v := reflect.ValueOf(in) if v.Kind() == reflect.Ptr { v = v.Elem() } if v.Kind() != reflect.Struct { // 非结构体返回错误提示 return nil, fmt.Errorf("ToMap only accepts struct or struct pointer; got %T", v) } t := v.Type() // 遍历结构体字段 // 指定tagName值为map中key;字段值为map中value for i := 0; i < v.NumField(); i++ { fi := t.Field(i) if tagValue := fi.Tag.Get(tagName); tagValue != "" { out[tagValue] = v.Field(i).Interface() } } return out, nil } func ZipOneFile(srcFile, dstZip string, pathFlag bool) error { zipFile, err := os.Create(dstZip) if err != nil { return err } defer zipFile.Close() zipWriter := zip.NewWriter(zipFile) defer zipWriter.Close() fileToCompress, err := os.Open(srcFile) if err != nil { return err } defer fileToCompress.Close() var fileInZip io.Writer if pathFlag { fileInZip, err = zipWriter.Create(srcFile) if err != nil { return err } } else { // 获取文件的基本名称 fileName := filepath.Base(fileToCompress.Name()) fileInZip, err = zipWriter.Create(fileName) if err != nil { return err } } _, err = io.Copy(fileInZip, fileToCompress) if err != nil { return err } return nil } func ZipDirectoryFile(srcDir, dstZip string) error { // Create a new zip file zipfileWriter, err := os.Create(dstZip) if err != nil { return err } defer zipfileWriter.Close() // Create a new zip archive zipWriter := zip.NewWriter(zipfileWriter) defer zipWriter.Close() // Walk through the directory and add files to the zip archive err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } // Create a new file header for the current file header, err := zip.FileInfoHeader(info) if err != nil { return err } // Set the name of the file within the zip archive header.Name = filepath.Join(filepath.Base(srcDir), path[len(srcDir):]) // If the current file is a directory, skip it if info.IsDir() { return nil } // Create a new file in the zip archive fileWriter, err := zipWriter.CreateHeader(header) if err != nil { return err } // Open the current file file, err := os.Open(path) if err != nil { return err } defer file.Close() // Copy the contents of the current file to the zip archive _, err = io.Copy(fileWriter, file) if err != nil { return err } return nil }) return err } // 判断软件包是rpm或者deb, 1:rpm, 2:deb, 0:unknown format func JudgeRpmOrDebPackage(filePath string) (int, error) { var fileType int = 0 file, err := os.Open(filePath) if err != nil { return fileType, err } defer file.Close() // Read the first 6 bytes of the file header := make([]byte, 6) _, err = file.Read(header) if err != nil { return fileType, err } // Check the magic numbers to determine the package format if string(header) == "!" { fileType = 1 } else if string(header) == "!\n" magic := []byte("!\n") buffer := make([]byte, len(magic)) _, err := file.Read(buffer) if err != nil && err != io.EOF { return false } return string(buffer) == string(magic) } func CheckRpmOrDebPackage(filePath string) (int, error) { var fileType int = 0 file, err := os.Open(filePath) if err != nil { return fileType, err } defer file.Close() isRpm := isRpmPackage(file) isDeb := isDebPackage(file) if isRpm { fileType = 1 } else if isDeb { fileType = 2 } else { fileType = 0 } return fileType, nil } func IsRpmOrDebPackage(filePath string) int { var fileType int = 0 if strings.Contains(filePath, ".rpm") { fileType = 1 } else if strings.Contains(filePath, ".deb") { fileType = 2 } else { fileType = 0 } return fileType }