package CommonUtil import ( "bufio" "bytes" "dsBaseRpc/Const" "dsBaseRpc/Utils/IdCardUtil" "encoding/json" "errors" "fmt" uuid "github.com/satori/go.uuid" "io" "log" "math/rand" "net" "net/http" "os" "os/exec" "path/filepath" "reflect" "regexp" "strconv" "strings" "time" ) /** 功能:删除多余的空格 作者:黄海 时间:2020-04-03 */ func DeleteExtraSpace(s string) string { //删除字符串中的多余空格,有多个空格时,仅保留一个空格 s1 := strings.Replace(s, " ", " ", -1) //替换tab为空格 regstr := "\\s{2,}" //两个及两个以上空格的正则表达式 reg, _ := regexp.Compile(regstr) //编译正则表达式 s2 := make([]byte, len(s1)) //定义字符数组切片 copy(s2, s1) //将字符串复制到切片 spc_index := reg.FindStringIndex(string(s2)) //在字符串中搜索 for len(spc_index) > 0 { //找到适配项 s2 = append(s2[:spc_index[0]+1], s2[spc_index[1]:]...) //删除多余空格 spc_index = reg.FindStringIndex(string(s2)) //继续在字符串中搜索 } return string(s2) } /** 功能:带回显的执行DOS命令 作者:黄海 时间:2020-05-18 */ func Exec(name string, args ...string) error { cmd := exec.Command(name, args...) stderr, _ := cmd.StderrPipe() stdout, _ := cmd.StdoutPipe() if err := cmd.Start(); err != nil { log.Println("exec the cmd ", name, " failed") return err } // 正常日志 logScan := bufio.NewScanner(stdout) go func() { for logScan.Scan() { log.Println(logScan.Text()) } }() // 错误日志 errBuf := bytes.NewBufferString("") scan := bufio.NewScanner(stderr) for scan.Scan() { s := scan.Text() log.Println("", s) errBuf.WriteString(s) errBuf.WriteString("\n") } // 等待命令执行完 cmd.Wait() if !cmd.ProcessState.Success() { // 执行失败,返回错误信息 return errors.New(errBuf.String()) } return nil } //删除字符串中的空白行 func DeleteBlankString(str string) string { var arr = strings.Split(str, "\r\n") var resultStr = "" for i := 0; i < len(arr); i++ { if len(strings.Replace(strings.Replace(arr[i], " ", "", -1), "\t", "", -1)) > 0 { resultStr += arr[i] + "\r\n" } } return resultStr } //删除文件中空白行 func DeleteBlankFile(srcFilePah string, destFilePath string) error { srcFile, err := os.OpenFile(srcFilePah, os.O_RDONLY, 0666) defer srcFile.Close() if err != nil { return err } srcReader := bufio.NewReader(srcFile) destFile, err := os.OpenFile(destFilePath, os.O_WRONLY|os.O_CREATE, 0666) defer destFile.Close() if err != nil { return err } for { str, err := srcReader.ReadString('\n') if err != nil { if err == io.EOF { fmt.Print("The file end is touched.") break } else { return err } } if strings.HasSuffix(str, " \r\n") { continue } if strings.HasPrefix(str, "\r\n") { continue } fmt.Println(len(str)) fmt.Print(str) destFile.WriteString(str) } return nil } /** 功能:获取UUID 作者:黄海 时间:2020-02-03 */ func GetUUID() string { u2 := strings.ToUpper(uuid.NewV4().String()) return u2 } /** 功能:从一个数据库的查询返回结果中获取指定字段的IDS 作者:黄海 时间:2020-02-14 */ func Ids(list []map[string]interface{}, key string) []string { var ids []string for i := 0; i < len(list); i++ { switch list[i][key].(type) { case string: ids = append(ids, list[i][key].(string)) break case int64: ids = append(ids, strconv.FormatInt(list[i][key].(int64), 10)) } } return ids } /** 功能:判断是不是合法的日期格式 作者:黄海 时间:2020-03-23 */ func IsDate(date string) bool { _, err := time.Parse("2006-01-02 15:04:05", date) if err != nil { return false } else { return true } } /** 功能:判断是不是合法的Email 作者:黄海 时间:2020-03-23 */ func IsEmail(email string) bool { pattern := `^[0-9a-z][_.0-9a-z-]{0,31}@([0-9a-z][0-9a-z-]{0,30}[0-9a-z]\.){1,4}[a-z]{2,4}$` reg := regexp.MustCompile(pattern) return reg.MatchString(email) } /** 功能:判断是不是合法的身份证号 作者:黄海 时间:2020-06-16 */ func IsIdCard(idCard string) bool { IdCardNo := []byte(idCard) return IdCardUtil.IsValidIdCardNo(&IdCardNo) } /** 功能:获取蛇形命名的字符串 作者:黄海 时间:2020-01-22 */ func GetSnakeCaseStr(str string) string { array := strings.Split(str, "_") var result string for i := 0; i < len(array); i++ { result = result + strings.ToUpper(array[i][0:1]) + array[i][1:] } return result } /** 功能:将int数据类型转为int64 作者:黄海 时间:2020-02-18 */ func ConvertIntToInt64(i int) int64 { s := strconv.Itoa(i) s64, _ := strconv.ParseInt(s, 10, 64) return s64 } /** 功能:将字符串转为整数 作者:黄海 时间:2020-06-03 */ func ConvertStringToInt(s string) int { int, _ := strconv.Atoi(s) return int } /** 功能:将整数转为字符串 作者:黄海 时间:2020-05-30 */ func ConvertIntToString(i int) string { return strconv.Itoa(i) } /** 功能:获取当前的时间戳,精确度纳秒 作者:黄海 时间:2020-02-18 */ func GetCurrentTimestamp() int64 { return time.Now().UnixNano() } /** 功能:获取当前的时间字符串 作者:黄海 时间:2020-02-21 */ func GetCurrentTime() string { timeStr := time.Now().Format("2006-01-02 15:04:05") //当前时间的字符串,2006-01-02 15:04:05据说是golang的诞生时间,固定写法 return timeStr } /** 功能:判断所给路径文件/文件夹是否存在 作者: 黄海 时间:2020-03-26 */ func Exists(path string) bool { _, err := os.Stat(path) //os.Stat获取文件信息 if err != nil { if os.IsExist(err) { return true } return false } return true } /** 功能:获取访问的客户机IP 作者:黄海 时间:2020-03-26 */ func RemoteIp(req *http.Request) string { remoteAddr := req.RemoteAddr if ip := req.Header.Get("Remote_addr"); ip != "" { remoteAddr = ip } else { remoteAddr, _, _ = net.SplitHostPort(remoteAddr) } if remoteAddr == "::1" { remoteAddr = "127.0.0.1" } return remoteAddr } /** 功能:判断某一个值是否含在切片之中 作者:黄海 时间:2020-03-26 */ func InArray(need interface{}, haystack interface{}) bool { switch key := need.(type) { case int: for _, item := range haystack.([]int) { if item == key { return true } } case string: for _, item := range haystack.([]string) { if item == key { return true } } case int64: for _, item := range haystack.([]int64) { if item == key { return true } } case float64: for _, item := range haystack.([]float64) { if item == key { return true } } default: return false } return false } /** 功能:将整型数组转为字符串型数组 作者:黄海 时间:2020-04-12 */ func ConvertIntegerArrayToStringArray(nums []int) []string { return strings.Split(strings.Replace(fmt.Sprint(nums)[1:], "]", "", -1), " ") } /** 功能:将int64转化为string 作者:黄海 时间:2020-04-20 */ func ConvertInt64ToString(int64 int64) string { return strconv.FormatInt(int64, 10) } /** 功能:将int转化为string 作者:黄海 时间:2020-04-20 */ func ConvertInt32ToString(n int32) string { buf := [11]byte{} pos := len(buf) i := int64(n) signed := i < 0 if signed { i = -i } for { pos-- buf[pos], i = '0'+byte(i%10), i/10 if i == 0 { if signed { pos-- buf[pos] = '-' } return string(buf[pos:]) } } } /** 功能:将一个查询结果转化为字符串,方便返回 作者:黄海 时间:2020-04-22 */ func SerializeToString(list interface{}) string { switch list.(type) { case []map[string]interface{}: if len(list.([]map[string]interface{})) == 0 { return Const.BlankArrayString } else { data, _ := json.Marshal(list) return string(data) } case map[string]interface{}: data, _ := json.Marshal(list) return string(data) default: return "" } } /** 功能:将struct转为map 作者:黄海 时间:2020-05-20 */ func Struct2Map(obj interface{}) map[string]interface{} { t := reflect.TypeOf(obj) v := reflect.ValueOf(obj) var data = make(map[string]interface{}) for i := 0; i < t.NumField(); i++ { data[t.Field(i).Name] = v.Field(i).Interface() } return data } //将xormplus中生成的实例字段属性还原为表的列名称 func RerversMysqlColName(n string) string { fieldName := "" //需要写一个将蛇形命名法 for i := 0; i < len(n); i++ { ch := n[i] //大写字母 if ch >= 65 && ch <= 90 { if i > 0 { //如果不是开头第一个,那么需要添加一个_,这个是东师微服务的数据库表命名规则要求的。 fieldName += "_" + fmt.Sprintf("%c", ch+32) } else { fieldName += fmt.Sprintf("%c", ch+32) } } else { fieldName += fmt.Sprintf("%c", ch) } } return fieldName } //获取需要更新的字段有哪些 func GetNeedUpdateFields(model interface{}) []string { var arr []string //将结构体转为map _map := Struct2Map(model) //遍历map for n, v := range _map { //字段名称 //转化为表的名称,这个有些笨,但没有好的办法,黄海自力更新吧~ fieldName := RerversMysqlColName(n) switch v.(type) { case string: //如果是字符串类型,而且非空 if len(strings.Trim(v.(string), "")) > 0 { arr = append(arr, fieldName) } break case int64: if v.(int64) != 0 { arr = append(arr, fieldName) } break case int32: if v.(int32) != 0 { arr = append(arr, fieldName) } break case float32: if v.(float32) != 0 { arr = append(arr, fieldName) } break case float64: if v.(float64) != 0 { arr = append(arr, fieldName) } break default: arr = append(arr, fieldName) break } } return arr } //数组去重 func RemoveDuplicatesAndEmpty(a []string) (ret []string) { aLen := len(a) for i := 0; i < aLen; i++ { if (i > 0 && a[i-1] == a[i]) || len(a[i]) == 0 { continue } ret = append(ret, a[i]) } return } /** 功能:将一个JSON字符串转为map 作者:黄海 时间:2020-05-22 */ func ConvertJsonStringToMap(str string) map[string]interface{} { map2 := make(map[string]interface{}) err := json.Unmarshal([]byte(str), &map2) if err != nil { fmt.Println(err) } return map2 } /** 功能:将一个json字符串转为map数组 作者:黄海 时间:2020-05-12 */ func ConvertJsonStringToMapArray(str string) []map[string]interface{} { var dat []map[string]interface{} if err := json.Unmarshal([]byte(str), &dat); err == nil { return dat } else { return nil } } /** 功能:将一个数据库的查询结果,通过指定的字段返回一个数组并去重 作者:黄海 时间:2020-5-27 */ func ConvertSqlListToArray(_mapArray []map[string]interface{}, fieldName string) []string { var arr []string for i := range _mapArray { arr = append(arr, _mapArray[i][fieldName].(string)) } //去重 arr = RemoveDuplicatesAndEmpty(arr) return arr } /** 功能:产生6位随机数 作者:黄海 时间:2020-05-30 */ func GenValidateCode(width int) string { numeric := [10]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} r := len(numeric) rand.Seed(time.Now().UnixNano()) var sb strings.Builder for i := 0; i < width; i++ { fmt.Fprintf(&sb, "%d", numeric[rand.Intn(r)]) } return sb.String() } /** 功能:数组中是否存在某个字符串 作者:黄海 时间:2020-05-30 */ func IsContainString(items []string, item string) bool { for _, eachItem := range items { if eachItem == item { return true } } return false } func IsContainInt32(items []int32, item int32) bool { for _, eachItem := range items { if eachItem == item { return true } } return false } /** 功能:获取导出文件的随机位置 作者:黄海 时间:2020-06-18 */ func GetExportExcelFilePath() string { TargetPath, _ := os.Getwd() //生成随机的文件名 TargetPath = filepath.Dir(TargetPath) + "/dsBaseWeb/Html/ExcelTemp/" + GetUUID() + ".xlsx" return TargetPath } // 用sourceStruct的所有字段覆盖targetStruct的 // 如果fields不为空, 表示用sourceStruct的特定字段覆盖targetStruct的 // sourceStruct应该为结构体指针 即 &方式传递!!!! func CopyFields(sourceStruct interface{}, targetStruct interface{}, fields ...string) (err error) { at := reflect.TypeOf(targetStruct) av := reflect.ValueOf(targetStruct) bt := reflect.TypeOf(sourceStruct) bv := reflect.ValueOf(sourceStruct) // 简单判断下 if at.Kind() != reflect.Ptr { err = fmt.Errorf("targetStruct must be targetStruct struct pointer") return } av = reflect.ValueOf(av.Interface()) // 要复制哪些字段 _fields := make([]string, 0) if len(fields) > 0 { _fields = fields } else { for i := 0; i < bv.NumField(); i++ { _fields = append(_fields, bt.Field(i).Name) } } if len(_fields) == 0 { fmt.Println("no fields to copy") return } // 复制 for i := 0; i < len(_fields); i++ { name := _fields[i] f := av.Elem().FieldByName(name) bValue := bv.FieldByName(name) // a中有同名的字段并且类型一致才复制 if f.IsValid() && f.Kind() == bValue.Kind() { f.Set(bValue) } else { //fmt.Printf("no such field or different kind, fieldName: %s\n", name) } } return } // Convert json string to map func JsonToMap(jsonStr string) (map[string]string, error) { m := make(map[string]string) err := json.Unmarshal([]byte(jsonStr), &m) if err != nil { fmt.Printf("Unmarshal with error: %+v\n", err) return nil, err } for k, v := range m { fmt.Printf("%v: %v\n", k, v) } return m, nil } // Convert map json string func MapToJson(m map[string]interface{}) (string, error) { jsonByte, err := json.Marshal(m) if err != nil { fmt.Printf("Marshal with error: %+v\n", err) return "", nil } return string(jsonByte), nil } //利用正则表达式压缩字符串,去除空格或制表符 func CompressStr(str string) string { if str == "" { return "" } //匹配一个或多个空白符的正则表达式 reg := regexp.MustCompile("\\s+") return reg.ReplaceAllString(str, "") } //密码强度必须为字⺟⼤⼩写+数字+符号,8位以上 func CheckPasswordLevel(ps string) bool { if len(ps) < 8 { return false } num := `[0-9]{1}` a_z := `[a-z]{1}` A_Z := `[A-Z]{1}` symbol := `[!@#~$%^&*()+|_]{1}` if b, err := regexp.MatchString(num, ps); !b || err != nil { return false } if b, err := regexp.MatchString(a_z, ps); !b || err != nil { return false } if b, err := regexp.MatchString(A_Z, ps); !b || err != nil { return false } if b, err := regexp.MatchString(symbol, ps); !b || err != nil { return false } return true }