first commit
This commit is contained in:
commit
dc13f589c5
|
@ -0,0 +1,11 @@
|
|||
*.iml
|
||||
.idea/
|
||||
output/
|
||||
dockerfiles/
|
||||
log
|
||||
.DS_Store
|
||||
doc
|
||||
cmd/test
|
||||
go.sum
|
||||
pkg
|
||||
test.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)})
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue