From dc13f589c504b09836c301fc6994445163cc0c33 Mon Sep 17 00:00:00 2001 From: jiangyong Date: Tue, 20 Dec 2022 23:45:07 +0800 Subject: [PATCH] first commit --- .gitignore | 11 +++++ array.go | 93 +++++++++++++++++++++++++++++++++++++++++ encoding.go | 30 ++++++++++++++ file.go | 19 +++++++++ go.mod | 3 ++ http.go | 73 ++++++++++++++++++++++++++++++++ network.go | 20 +++++++++ number.go | 70 +++++++++++++++++++++++++++++++ string.go | 77 ++++++++++++++++++++++++++++++++++ time.go | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++ util.go | 77 ++++++++++++++++++++++++++++++++++ 11 files changed, 590 insertions(+) create mode 100644 .gitignore create mode 100644 array.go create mode 100644 encoding.go create mode 100644 file.go create mode 100644 go.mod create mode 100644 http.go create mode 100644 network.go create mode 100644 number.go create mode 100644 string.go create mode 100644 time.go create mode 100644 util.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9b31355 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*.iml +.idea/ +output/ +dockerfiles/ +log +.DS_Store +doc +cmd/test +go.sum +pkg +test.go diff --git a/array.go b/array.go new file mode 100644 index 0000000..c760df7 --- /dev/null +++ b/array.go @@ -0,0 +1,93 @@ +package goutil + +import "reflect" + +func Sort(data interface{}, fun interface{}) { + fValue := reflect.ValueOf(fun) + fType := fValue.Type() + dValue := reflect.Indirect(reflect.ValueOf(data)) + dType := dValue.Type() + + if (dType.Kind() != reflect.Slice && dType.Kind() != reflect.Array) || + fType.Kind() != reflect.Func || fType.NumIn() != 2 || fType.NumOut() != 1 { + panic("sort paramter type format error") + } + + firstType := fType.In(0) + secondType := fType.In(1) + outType := fType.Out(0) + elemType := dType.Elem() + if elemType.Kind() != firstType.Kind() || elemType.Kind() != secondType.Kind() || + outType.Kind() != reflect.Bool { + panic("sort elem type format error") + } + + tmp := reflect.Indirect(reflect.New(elemType)) + for i := 0; i < dValue.Len(); i++ { + for j := i + 1; j < dValue.Len(); j++ { + out := fValue.Call([]reflect.Value{dValue.Index(i), dValue.Index(j)}) + if out[0].Bool() { + continue + } + + tmp.Set(dValue.Index(i)) + dValue.Index(i).Set(dValue.Index(j)) + dValue.Index(j).Set(tmp) + } + } + +} + +func Filter(data interface{}, fun interface{}) { + fValue := reflect.ValueOf(fun) + fType := fValue.Type() + dValue := reflect.Indirect(reflect.ValueOf(data)) + dType := dValue.Type() + + if (dType.Kind() != reflect.Slice && dType.Kind() != reflect.Array) || + fType.Kind() != reflect.Func || fType.NumIn() != 1 || fType.NumOut() != 1 { + panic("sort paramter type format error") + } + + firstType := fType.In(0) + outType := fType.Out(0) + elemType := dType.Elem() + if elemType.Kind() != firstType.Kind() || outType.Kind() != reflect.Bool { + panic("sort elem type format error") + } + + pos := 0 + for i := 0; i < dValue.Len(); i++ { + out := fValue.Call([]reflect.Value{dValue.Index(i)}) + if !out[0].Bool() { + continue + } + + dValue.Index(pos).Set(dValue.Index(i)) + pos++ + } + + dValue.SetLen(pos) +} + +func Traverse(data interface{}, fun interface{}) { + fValue := reflect.ValueOf(fun) + fType := fValue.Type() + dValue := reflect.Indirect(reflect.ValueOf(data)) + dType := dValue.Type() + + if (dType.Kind() != reflect.Slice && dType.Kind() != reflect.Array) || + fType.Kind() != reflect.Func || fType.NumIn() != 1 || fType.NumOut() != 0 { + panic("sort paramter type format error") + } + + firstType := fType.In(0) + elemType := dType.Elem() + if elemType.Kind() != firstType.Kind() { + panic("sort elem type format error") + } + + for i := 0; i < dValue.Len(); i++ { + fValue.Call([]reflect.Value{dValue.Index(i)}) + } +} diff --git a/encoding.go b/encoding.go new file mode 100644 index 0000000..c099883 --- /dev/null +++ b/encoding.go @@ -0,0 +1,30 @@ +package goutil + +import ( + "encoding/json" + "encoding/xml" +) + +// EncodeJSON encode anything to json string +func EncodeJSON(v interface{}) string { + b, _ := json.Marshal(v) + return string(b) +} + +// EncodeJSON encode anything to json string +func EncodeJSONIndent(v interface{}) string { + b, _ := json.MarshalIndent(v, " ", " ") + return string(b) +} + +// EncodeJSON encode anything to json string +func EncodeXML(v interface{}) string { + b, _ := xml.Marshal(v) + return string(b) +} + +// EncodeJSON encode anything to json string +func EncodeXMLIndent(v interface{}) string { + b, _ := xml.MarshalIndent(v, " ", " ") + return string(b) +} diff --git a/file.go b/file.go new file mode 100644 index 0000000..6dce1b5 --- /dev/null +++ b/file.go @@ -0,0 +1,19 @@ +package goutil + +import "io/ioutil" + +func FileList(dirPath string) ([]string, error) { + lis, err := ioutil.ReadDir(dirPath) + if err != nil { + return nil, err + } + + fileList := make([]string, 0) + for _, f := range lis { + if f.IsDir() { + continue + } + fileList = append(fileList, f.Name()) + } + return fileList, nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..46c1b78 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/smbrave/goutil + +go 1.19 diff --git a/http.go b/http.go new file mode 100644 index 0000000..4e885d5 --- /dev/null +++ b/http.go @@ -0,0 +1,73 @@ +package goutil + +import ( + "bytes" + "crypto/tls" + "fmt" + "io" + "net/http" + "net/url" + "time" +) + +// PostJson 请求 +func HttpPost(link string, params map[string]string, json []byte) ([]byte, error) { + client := &http.Client{Timeout: 20 * time.Second} + //忽略https的证书 + client.Transport = &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + p := url.Values{} + u, _ := url.Parse(link) + if params != nil { + for k, v := range params { + p.Set(k, v) + } + } + u.RawQuery = p.Encode() + req, err := http.NewRequest("POST", u.String(), bytes.NewBuffer(json)) + if err != nil { + return nil, err + } + req.Header.Add("Content-Type", "application/json") + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("%d:%s", resp.StatusCode, resp.Status) + } + return io.ReadAll(resp.Body) +} + +// Get 请求 link:请求url +func HttpGet(link string, params map[string]string) ([]byte, error) { + client := &http.Client{Timeout: 20 * time.Second} + //忽略https的证书 + client.Transport = &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + p := url.Values{} + u, _ := url.Parse(link) + if params != nil { + for k, v := range params { + p.Set(k, v) + } + } + u.RawQuery = p.Encode() + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return nil, err + } + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("%d:%s", resp.StatusCode, resp.Status) + } + return io.ReadAll(resp.Body) +} diff --git a/network.go b/network.go new file mode 100644 index 0000000..9ce5bd3 --- /dev/null +++ b/network.go @@ -0,0 +1,20 @@ +package goutil + +import "net" + +func GetIp() string { + addrs, err := net.InterfaceAddrs() + + if err != nil { + return err.Error() + } + + for _, address := range addrs { + if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + return ipnet.IP.String() + } + } + } + return "none" +} diff --git a/number.go b/number.go new file mode 100644 index 0000000..d7d0554 --- /dev/null +++ b/number.go @@ -0,0 +1,70 @@ +package goutil + +import ( + "crypto/md5" + "sync" + "sync/atomic" + "time" +) + +func IsNumber(str string) bool { + for i := 0; i < len(str); i++ { + if str[i] != '-' && (str[i] < '0' || str[i] > '9') { + return false + } + } + return true +} + +// ID生成规则:32B secondtime + 6B sid + 6B flag + 20B autoinc, 每秒最大调用量为1048576 +var auto_inc_sig uint64 = 0 +var big_id_lock = new(sync.RWMutex) + +func GetBigID(sid int, flag int) uint64 { + localSig := atomic.AddUint64(&auto_inc_sig, 1) + bigID := uint64(time.Now().Unix()) + bigID = bigID<<20 | (localSig % (1 << 20)) //避免产生连续ID + bigID = bigID<<6 | (uint64(sid) % (1 << 6)) + bigID = bigID<<6 | (uint64(flag) % (1 << 6)) + return bigID +} + +func ParseBigID(bigID uint64) (int, int, int64) { + flag := int(bigID % (1 << 6)) + sid := int(bigID >> 6 % (1 << 6)) + tiemstamp := int64(bigID >> 32) + return sid, flag, tiemstamp +} + +// 取低8个字节作为digest的值 +func Hash64(s string) uint64 { + sum := md5.Sum([]byte(s)) + digest := uint64(0) + for i := 0; i < 8; i++ { + idx := uint64(sum[i]) + digest += (idx << uint64(i*8)) + } + return digest +} + +// 取低8个字节作为digest的值 +func Hash56(s string) uint64 { + sum := md5.Sum([]byte(s)) + digest := uint64(0) + for i := 0; i < 7; i++ { + idx := uint64(sum[i]) + digest += (idx << uint64(i*8)) + } + return digest +} + +// 取低8个字节作为digest的值 +func Hash32(s string) uint32 { + sum := md5.Sum([]byte(s)) + digest := uint32(0) + for i := 0; i < 4; i++ { + idx := uint32(sum[i]) + digest += (idx << uint64(i*8)) + } + return digest +} diff --git a/string.go b/string.go new file mode 100644 index 0000000..80a3e4e --- /dev/null +++ b/string.go @@ -0,0 +1,77 @@ +package goutil + +import ( + "crypto/md5" + "encoding/hex" + "math/rand" + "strings" + "time" +) + +func Md5(str string) string { + h := md5.New() + h.Write([]byte(str)) + return hex.EncodeToString(h.Sum(nil)) +} + +func StrInField(key string, str string) bool { + str = strings.ReplaceAll(str, ",", ",") + s1 := strings.Split(str, ",") + for _, v := range s1 { + if v == key { + return true + } + } + return false +} + +func StrInSlice(key string, slice []string) bool { + if len(slice) == 0 { + return false + } + + for _, v := range slice { + if v == key { + return true + } + } + + return false +} + +func StrInPrefix(s string, arr []string) bool { + for _, a := range arr { + if strings.HasPrefix(s, a) { + return true + } + } + return false +} + +// ArrayUnique 数组去重 +func StrUnique(arr []string) []string { + set := make(map[string]bool) + j := 0 + for _, v := range arr { + _, ok := set[v] + if ok { + continue + } + set[v] = true + arr[j] = v + j++ + } + return arr[:j] +} + +// 生成随机字符串 +func RandomStr(length int64) string { + str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + bytes := []byte(str) + result := []byte{} + r := rand.New(rand.NewSource(time.Now().UnixNano())) + for i := int64(0); i < length; i++ { + result = append(result, bytes[r.Intn(len(bytes))]) + } + return string(result) +} diff --git a/time.go b/time.go new file mode 100644 index 0000000..d1d137a --- /dev/null +++ b/time.go @@ -0,0 +1,117 @@ +package goutil + +import ( + "fmt" + "time" +) + +// 时间戳转为日期 +func TimeToDate(t int64) string { + tm := time.Unix(t, 0) + return tm.Format("2006-01-02") +} + +// 时间戳转为datetime格式 +func TimeToDateTime(t int64) string { + tm := time.Unix(t, 0) + return tm.Format("2006-01-02 15:04:05") +} + +// 日期转为时间戳 +func DateTimeToTime(date string) int64 { + var LOC, _ = time.LoadLocation("Asia/Shanghai") + tim, _ := time.ParseInLocation("2006-01-02 15:04:05", date, LOC) + return tim.Unix() +} + +func GetNowTime() string { + return time.Now().Format("2006-01-02 15:04:05") +} + +// 获取一天开始的时间戳 +func GetTodayStartTime() int64 { + now := time.Now().Unix() + return now - (now+28800)%86400 +} + +// 获取一周开始的时间戳 +func GetWeekStartTime() int64 { + now := time.Now() + week := int(now.Weekday()) + if week == 0 { + week = 7 + } + t := now.AddDate(0, 0, 1-week).Unix() + return t - (t+28800)%86400 +} + +// 获取一月开始的时间戳 +func GetMonthStartTime() int64 { + now := time.Now().AddDate(0, 0, 1-time.Now().Day()).Unix() + return now - (now+28800)%86400 +} + +func TimeToWeek(t int64) string { + week := time.Unix(t, 0) + switch week.Weekday() { + case time.Monday: + return "星期一" + case time.Tuesday: + return "星期二" + case time.Wednesday: + return "星期三" + case time.Thursday: + return "星期四" + case time.Friday: + return "星期五" + case time.Saturday: + return "星期六" + case time.Sunday: + return "星期天" + } + return "" +} + +// 时间戳转时间提示 +func TimeToTips(t int64) string { + now := time.Now().Unix() + span := now - t + + result := "" + if span > 0 { + if span < 60 { + result = "刚刚" + } else if span <= 1800 { + result = fmt.Sprintf("%d分钟前", span/60) + } else if span <= 3600 { + result = "半小时前" + } else if span <= 86400 { + result = fmt.Sprintf("%d小时前", span/3600) + } else if span <= 86400*30 { + result = fmt.Sprintf("%d天前", span/(86400)) + } else if span <= 86400*30*12 { + result = fmt.Sprintf("%d月前", span/(86400*30)) + } else { + result = fmt.Sprintf("%d年前", span/(86400*30*12)) + } + } else { + span = 0 - span + if span < 60 { + result = fmt.Sprintf("%d秒后", span) + } else if span <= 1800 { + result = fmt.Sprintf("%d分钟后", span/60) + } else if span <= 3600 { + result = "半小时后" + } else if span <= 86400 { + result = fmt.Sprintf("%d小时后", span/3600) + } else if span <= 86400*30 { + result = fmt.Sprintf("%d天后", span/(86400)) + } else if span <= 86400*30*12 { + result = fmt.Sprintf("%d月后", span/(86400*30)) + } else { + result = fmt.Sprintf("%d年后", span/(86400*30*12)) + } + } + + return result +} diff --git a/util.go b/util.go new file mode 100644 index 0000000..05aecc6 --- /dev/null +++ b/util.go @@ -0,0 +1,77 @@ +package goutil + +import ( + "errors" + "fmt" + "reflect" +) + +// format bytes number friendly +func BytesToTips(bytes uint64) string { + switch { + case bytes < 1024: + return fmt.Sprintf("%dB", bytes) + case bytes < 1024*1024: + return fmt.Sprintf("%.2fK", float64(bytes)/1024) + case bytes < 1024*1024*1024: + return fmt.Sprintf("%.2fM", float64(bytes)/1024/1024) + default: + return fmt.Sprintf("%.2fG", float64(bytes)/1024/1024/1024) + } +} + +func If[T any](condition bool, trueVal, falseVal T) T { + if condition { + return trueVal + } + return falseVal +} + +func CopyStruct(dst interface{}, src interface{}) { + + dtype := reflect.TypeOf(dst) + stype := reflect.TypeOf(src) + + if stype.Kind() != reflect.Ptr || stype.Kind() != dtype.Kind() { + panic(errors.New("src/dst must ptr")) + } + if reflect.ValueOf(dst).IsNil() || reflect.ValueOf(src).IsNil() { + panic(errors.New("src/dst is nil")) + } + + dval := reflect.ValueOf(dst).Elem() + sval := reflect.ValueOf(src).Elem() + + for i := 0; i < sval.NumField(); i++ { + sValue := sval.Field(i) + + dValue := dval.FieldByName(sval.Type().Field(i).Name) + if sValue.IsZero() || dValue.IsValid() == false || !dValue.CanSet() { + continue + } + if sValue.Kind() != dValue.Kind() { + continue + } + + switch sValue.Type().Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + dValue.SetInt(sValue.Int()) + + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + dValue.SetUint(sValue.Uint()) + + case reflect.Float32, reflect.Float64: + dValue.SetFloat(sValue.Float()) + + case reflect.String: + dValue.SetString(sValue.String()) + + case reflect.Bool: + dValue.SetBool(sValue.Bool()) + + case reflect.Ptr: + CopyStruct(dValue.Interface(), sValue.Interface()) + } + } + +}