You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

692 lines
14 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
}