From b9831ccd29a0f0298414bd094990e430ddbb1c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=85=89=E6=98=A5?= Date: Sat, 9 Apr 2022 17:21:12 +0800 Subject: [PATCH] update utils --- go.mod | 103 ---------------------- utils/goaes/goaes.go | 57 ++++++++++++ utils/goarray/goarray.go | 17 ++++ utils/gobase64/gobase64.go | 5 +- utils/godecimal/godecimal.go | 2 +- utils/godmail/go.sum | 4 + utils/goenv/goenv.go | 22 +++++ utils/gofiles/gofiles.go | 104 +++------------------- utils/gofloat/gofloat.go | 13 +++ utils/goget/goget.go | 15 ++++ utils/gohttp/gohttp.go | 4 +- utils/goint/goint.go | 16 ++++ utils/goint64/goint64.go | 23 +++++ utils/goip/goip.go | 73 ++++++++++++++++ utils/gojson/gojson.go | 47 ++++++++++ utils/golock/lock.go | 10 +-- utils/gomac/gomac.go | 21 +++++ utils/gomd5/gomd5.go | 49 +++++++++++ utils/gomysql/app.go | 4 +- utils/goorder/goorder.go | 12 +++ utils/gophp/gophp.go | 89 +------------------ utils/gophp/serialize/serialize.go | 2 +- utils/gophp/serialize/unserialize.go | 2 +- utils/gopostgresql/app.go | 1 + utils/gopreg/gopreg.go | 30 +++++++ utils/gorandom/gorandom.go | 45 ++++++++++ utils/gorsa/gorsa.go | 77 +++++++++++++++++ utils/gosort/gosort.go | 26 ++++++ utils/gossh/gossh.go | 66 ++++++++++++++ utils/gossl/gossl.go | 43 ++++++++++ utils/gotime/Tomorrow.go | 15 ++++ utils/gotime/app.go | 91 ++++++++++++++++++++ utils/gotime/differ.go | 69 +++++++++++++++ utils/gotime/errors.go | 8 ++ utils/gotime/location.go | 14 +++ utils/gotime/start_end.go | 124 +++++++++++++++++++++++++++ utils/gotime/today.go | 112 ++++++++++++++++++++++++ utils/gotime/yesterday.go | 17 ++++ utils/gouuid/gouuid.go | 18 ++++ utils/phpjson/phpjson.go | 50 +++++++++++ 40 files changed, 1198 insertions(+), 302 deletions(-) create mode 100644 utils/goaes/goaes.go create mode 100644 utils/goarray/goarray.go create mode 100644 utils/godmail/go.sum create mode 100644 utils/goenv/goenv.go create mode 100644 utils/gofloat/gofloat.go create mode 100644 utils/goget/goget.go create mode 100644 utils/goint/goint.go create mode 100644 utils/goint64/goint64.go create mode 100644 utils/goip/goip.go create mode 100644 utils/gojson/gojson.go create mode 100644 utils/gomac/gomac.go create mode 100644 utils/gomd5/gomd5.go create mode 100644 utils/goorder/goorder.go create mode 100644 utils/gopreg/gopreg.go create mode 100644 utils/gorandom/gorandom.go create mode 100644 utils/gorsa/gorsa.go create mode 100644 utils/gosort/gosort.go create mode 100644 utils/gossh/gossh.go create mode 100644 utils/gossl/gossl.go create mode 100644 utils/gotime/Tomorrow.go create mode 100644 utils/gotime/app.go create mode 100644 utils/gotime/differ.go create mode 100644 utils/gotime/errors.go create mode 100644 utils/gotime/location.go create mode 100644 utils/gotime/start_end.go create mode 100644 utils/gotime/today.go create mode 100644 utils/gotime/yesterday.go create mode 100644 utils/gouuid/gouuid.go create mode 100644 utils/phpjson/phpjson.go diff --git a/go.mod b/go.mod index cb9f482f..c4acb1cc 100644 --- a/go.mod +++ b/go.mod @@ -1,106 +1,3 @@ module github.com/dtapps/go-library go 1.18 - -require ( - github.com/dtapps/go-library/service v0.0.0-20220320092139-34887507f205 - github.com/dtapps/go-library/utils v0.0.0-20220320092139-34887507f205 -) - -require ( - github.com/dtapps/go-library/service/dingdanxia v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/dingtalk v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/eastiot v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/ejiaofei v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/ip v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/jd v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/kashangwl v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/meituan v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/pinduoduo v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/pintoto v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/taobao v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/tianyancha v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/wechatminiprogram v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/wechatoffice v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/wechatpayapiv3 v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/wechatqy v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/wechatunion v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/service/wikeyun v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/goaes v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/goarray v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gobase64 v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/godecimal v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/godmail v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/goenv v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gofiles v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gofloat v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/goget v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/goheader v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gohttp v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/goint v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/goint64 v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/goip v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gojson v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/goless v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/golock v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/golog v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gomac v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gomd5 v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gomongo v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gomysql v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/goparams v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gophp v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gopostgresql v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gopreg v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gorandom v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/goredis v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gorequest v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gorsa v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gosort v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gossh v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gossl v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gostring v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gotime v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gourl v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/gouuid v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/phpjson v0.0.0-20220320092139-34887507f205 // indirect - github.com/dtapps/go-library/utils/rmb v0.0.0-20220320092139-34887507f205 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/go-redis/redis/v8 v8.11.5 // indirect - github.com/go-sql-driver/mysql v1.6.0 // indirect - github.com/go-stack/stack v1.8.1 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.11.0 // indirect - github.com/jackc/pgio v1.0.0 // indirect - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.2.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect - github.com/jackc/pgtype v1.10.0 // indirect - github.com/jackc/pgx/v4 v4.15.0 // indirect - github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect - github.com/klauspost/compress v1.15.1 // indirect - github.com/natefinch/lumberjack v2.0.0+incompatible // indirect - github.com/nilorg/sdk v0.0.0-20210429091026-95b6cdc95c84 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/shopspring/decimal v1.3.1 // indirect - github.com/xdg-go/pbkdf2 v1.0.0 // indirect - github.com/xdg-go/scram v1.1.1 // indirect - github.com/xdg-go/stringprep v1.0.3 // indirect - github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect - go.mongodb.org/mongo-driver v1.8.4 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.8.0 // indirect - go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect - golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 // indirect - golang.org/x/text v0.3.7 // indirect - gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect - gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect - gorm.io/driver/mysql v1.3.2 // indirect - gorm.io/driver/postgres v1.3.1 // indirect - gorm.io/gorm v1.23.3 // indirect -) diff --git a/utils/goaes/goaes.go b/utils/goaes/goaes.go new file mode 100644 index 00000000..3692ec2e --- /dev/null +++ b/utils/goaes/goaes.go @@ -0,0 +1,57 @@ +package goaes + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "encoding/base64" +) + +// Encrypt 加密 aes_128_cbc +func Encrypt(encryptStr string, key []byte, iv string) (string, error) { + encryptBytes := []byte(encryptStr) + block, err := aes.NewCipher(key) + if err != nil { + return "", err + } + + blockSize := block.BlockSize() + encryptBytes = pkcs5Padding(encryptBytes, blockSize) + + blockMode := cipher.NewCBCEncrypter(block, []byte(iv)) + encrypted := make([]byte, len(encryptBytes)) + blockMode.CryptBlocks(encrypted, encryptBytes) + return base64.URLEncoding.EncodeToString(encrypted), nil +} + +// Decrypt 解密 +func Decrypt(decryptStr string, key []byte, iv string) (string, error) { + decryptBytes, err := base64.URLEncoding.DecodeString(decryptStr) + if err != nil { + return "", err + } + + block, err := aes.NewCipher(key) + if err != nil { + return "", err + } + + blockMode := cipher.NewCBCDecrypter(block, []byte(iv)) + decrypted := make([]byte, len(decryptBytes)) + + blockMode.CryptBlocks(decrypted, decryptBytes) + decrypted = pkcs5UnPadding(decrypted) + return string(decrypted), nil +} + +func pkcs5Padding(cipherText []byte, blockSize int) []byte { + padding := blockSize - len(cipherText)%blockSize + padText := bytes.Repeat([]byte{byte(padding)}, padding) + return append(cipherText, padText...) +} + +func pkcs5UnPadding(decrypted []byte) []byte { + length := len(decrypted) + unPadding := int(decrypted[length-1]) + return decrypted[:(length - unPadding)] +} diff --git a/utils/goarray/goarray.go b/utils/goarray/goarray.go new file mode 100644 index 00000000..41f2c2ed --- /dev/null +++ b/utils/goarray/goarray.go @@ -0,0 +1,17 @@ +package goarray + +func Grouping() { + +} + +func TurnString(ss []string) (s string) { + sl := len(ss) + for k, v := range ss { + if k+1 == sl { + s = s + v + } else { + s = s + v + "," + } + } + return s +} diff --git a/utils/gobase64/gobase64.go b/utils/gobase64/gobase64.go index 13dc9459..4154c968 100644 --- a/utils/gobase64/gobase64.go +++ b/utils/gobase64/gobase64.go @@ -1,9 +1,6 @@ package gobase64 -import ( - "dtapps/dta/library/utils/gophp" - "encoding/base64" -) +import "encoding/base64" // Encode base64编码 func Encode(input string) string { diff --git a/utils/godecimal/godecimal.go b/utils/godecimal/godecimal.go index 19dafd55..2b5c7b8e 100644 --- a/utils/godecimal/godecimal.go +++ b/utils/godecimal/godecimal.go @@ -1,8 +1,8 @@ package godecimal import ( - "dtapps/dta/library/utils/gostring" "fmt" + "github.com/dtapps/go-library/utils/gostring" "math" "strconv" ) diff --git a/utils/godmail/go.sum b/utils/godmail/go.sum new file mode 100644 index 00000000..b530e335 --- /dev/null +++ b/utils/godmail/go.sum @@ -0,0 +1,4 @@ +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= +gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= +gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= diff --git a/utils/goenv/goenv.go b/utils/goenv/goenv.go new file mode 100644 index 00000000..daaef4af --- /dev/null +++ b/utils/goenv/goenv.go @@ -0,0 +1,22 @@ +package goenv + +import ( + "github.com/dtapps/go-library/utils/gostring" + "os" +) + +func GetEnvDefault(key, defVal string) string { + val, ok := os.LookupEnv(key) + if ok { + return val + } + return defVal +} + +func GetEnvDefaultInt(key string, defVal int) int { + val, ok := os.LookupEnv(key) + if ok { + return gostring.ToInt(val) + } + return defVal +} diff --git a/utils/gofiles/gofiles.go b/utils/gofiles/gofiles.go index 4d191395..b4e5332d 100644 --- a/utils/gofiles/gofiles.go +++ b/utils/gofiles/gofiles.go @@ -1,9 +1,7 @@ package gofiles import ( - "fmt" "log" - "math" "os" ) @@ -43,10 +41,16 @@ func ExistFile(pathName string) (bool, error) { return false, err } -// CheckNotExist 判断文件夹是否存在 -func CheckNotExist(path string) bool { +// ExistFiles 判断文件夹是否存在 +func ExistFiles(path string) (bool, error) { _, err := os.Stat(path) - return os.IsNotExist(err) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err } // CreateFile 创建文件 @@ -90,96 +94,8 @@ func CreateDir(path string) error { if !dirExist { err := os.Mkdir(path, os.ModePerm) if err != nil { - log.Printf("创建[%s]目录失败: %s\n", path) + log.Printf("创建[%s]目录失败: %s\n", path, err) } } return err } - -// FileSize calculates the file size and generate user-friendly string. -func FileSize(s uint64) string { - sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"} - return humanateBytes(s, 1024, sizes) -} -func humanateBytes(s uint64, base float64, sizes []string) string { - if s < 10 { - return fmt.Sprintf("%d B", s) - } - e := math.Floor(logn(float64(s), base)) - suffix := sizes[int(e)] - val := float64(s) / math.Pow(base, math.Floor(e)) - f := "%.0f" - if val < 10 { - f = "%.1f" - } - - return fmt.Sprintf(f+" %s", val, suffix) -} - -func logn(n, b float64) float64 { - return math.Log(n) / math.Log(b) -} - -// CheckPermission 检查文件是否有权限 -func CheckPermission(src string) bool { - _, err := os.Stat(src) - - return os.IsPermission(err) -} - -// IsNotExistMkDir create a directory if it does not exist -func IsNotExistMkDir(src string) error { - if notExist := CheckNotExist(src); notExist == true { - if err := MkDir(src); err != nil { - return err - } - } - - return nil -} - -// MkDir 创建一个目录 -func MkDir(src string) error { - err := os.MkdirAll(src, os.ModePerm) - if err != nil { - return err - } - - return nil -} - -// Open 根据特定模式的文件 -func Open(name string, flag int, perm os.FileMode) (*os.File, error) { - f, err := os.OpenFile(name, flag, perm) - if err != nil { - return nil, err - } - - return f, nil -} - -// MustOpen 试图打开文件 -func MustOpen(fileName, filePath string) (*os.File, error) { - dir, err := os.Getwd() - if err != nil { - return nil, fmt.Errorf("os.Getwd err: %v", err) - } - - src := dir + "/" + filePath - perm := CheckPermission(src) - if perm == true { - return nil, fmt.Errorf("file.CheckPermission Permission denied src: %s", src) - } - - err = IsNotExistMkDir(src) - if err != nil { - return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err) - } - - f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644) - if err != nil { - return nil, fmt.Errorf("fail to OpenFile :%v", err) - } - - return f, nil -} diff --git a/utils/gofloat/gofloat.go b/utils/gofloat/gofloat.go new file mode 100644 index 00000000..1d7585a0 --- /dev/null +++ b/utils/gofloat/gofloat.go @@ -0,0 +1,13 @@ +package float + +import "math" + +// ToInt64 将float64转成精确的int64 +func ToInt64(num float64, retain int) int64 { + return int64(num * math.Pow10(retain)) +} + +// ToFloat64 精准float64 +func ToFloat64(num float64, retain int) float64 { + return num * math.Pow10(retain) +} diff --git a/utils/goget/goget.go b/utils/goget/goget.go new file mode 100644 index 00000000..1436d96f --- /dev/null +++ b/utils/goget/goget.go @@ -0,0 +1,15 @@ +package goget + +func GetDefault(key, defVal any) any { + if key != nil { + return key + } + return defVal +} + +func GetStringDefault(key, defVal string) string { + if key != "" { + return key + } + return defVal +} diff --git a/utils/gohttp/gohttp.go b/utils/gohttp/gohttp.go index 898b74af..406de138 100644 --- a/utils/gohttp/gohttp.go +++ b/utils/gohttp/gohttp.go @@ -3,11 +3,11 @@ package gohttp import ( "bytes" "crypto/tls" - "dtapps/dta/library/utils/goheader" - "dtapps/dta/library/utils/gorequest" "encoding/json" "errors" "fmt" + "github.com/dtapps/go-library/utils/goheader" + "github.com/dtapps/go-library/utils/gorequest" "io" "io/ioutil" "net/http" diff --git a/utils/goint/goint.go b/utils/goint/goint.go new file mode 100644 index 00000000..2cc1f290 --- /dev/null +++ b/utils/goint/goint.go @@ -0,0 +1,16 @@ +package goint + +import ( + "math" + "strconv" +) + +// ToString int到string +func ToString(n int) string { + return strconv.Itoa(n) +} + +// ToFloat64 int到float64 +func ToFloat64(n int) float64 { + return float64(n) / math.Pow10(0) +} diff --git a/utils/goint64/goint64.go b/utils/goint64/goint64.go new file mode 100644 index 00000000..20fe1aac --- /dev/null +++ b/utils/goint64/goint64.go @@ -0,0 +1,23 @@ +package goint64 + +import "math" + +// ToFloat64 int64到float64 +func ToFloat64(n int64) float64 { + return float64(n) / math.Pow10(0) +} + +// ToUnwrap 将int64恢复成正常的float64 +func ToUnwrap(num int64, retain int) float64 { + return float64(num) / math.Pow10(retain) +} + +// ToUnwrapToInt64 精准int64 +func ToUnwrapToInt64(num int64, retain int) int64 { + return int64(ToUnwrap(num, retain)) +} + +// ToFloat64NewWiFi 返回float64 +func ToFloat64NewWiFi(num int64) float64 { + return float64(num / 100) +} diff --git a/utils/goip/goip.go b/utils/goip/goip.go new file mode 100644 index 00000000..61ed801f --- /dev/null +++ b/utils/goip/goip.go @@ -0,0 +1,73 @@ +package goip + +import ( + "encoding/json" + "github.com/dtapps/go-library/utils/gohttp" + "log" + "net" +) + +// GetInsideIp 内网ip +func GetInsideIp() string { + conn, err := net.Dial("udp", "8.8.8.8:80") + if err != nil { + log.Fatal(err) + } + defer conn.Close() + + localAddr := conn.LocalAddr().(*net.UDPAddr) + return localAddr.IP.String() +} + +var respGetOutsideIp struct { + Ip string `json:"ip"` +} + +// GetOutsideIp 外网ip +func GetOutsideIp() string { + get, _ := gohttp.Get("https://api.dtapp.net/ip", map[string]interface{}{}) + _ = json.Unmarshal(get.Body, &respGetOutsideIp) + if respGetOutsideIp.Ip != "" { + return respGetOutsideIp.Ip + } + return "0.0.0.0" +} + +func GetOutboundIP() string { + conn, err := net.Dial("udp", "8.8.8.8:80") + if err != nil { + log.Fatal(err) + } + defer conn.Close() + + localAddr := conn.LocalAddr().(*net.UDPAddr) + return localAddr.IP.String() +} + +// Ips 获取全部网卡的全部IP +func Ips() (map[string]string, error) { + + ips := make(map[string]string) + + //返回 interface 结构体对象的列表,包含了全部网卡信息 + interfaces, err := net.Interfaces() + if err != nil { + return nil, err + } + + //遍历全部网卡 + for _, i := range interfaces { + + // Addrs() 方法返回一个网卡上全部的IP列表 + address, err := i.Addrs() + if err != nil { + return nil, err + } + + //遍历一个网卡上全部的IP列表,组合为一个字符串,放入对应网卡名称的map中 + for _, v := range address { + ips[i.Name] += v.String() + " " + } + } + return ips, nil +} diff --git a/utils/gojson/gojson.go b/utils/gojson/gojson.go new file mode 100644 index 00000000..a1e046bd --- /dev/null +++ b/utils/gojson/gojson.go @@ -0,0 +1,47 @@ +package gojson + +import "encoding/json" + +func Encode(v interface{}) (string, error) { + bytes, err := json.Marshal(v) + if err != nil { + return "", err + } + return string(bytes), nil +} + +func MarshalToString(msg interface{}) (string, error) { + j, e := json.Marshal(msg) + if e != nil { + return "", e + } + return string(j), nil +} + +func JsonDecode(data string) (map[string]interface{}, error) { + var dat map[string]interface{} + err := json.Unmarshal([]byte(data), &dat) + return dat, err +} + +func JsonDecodeNoError(data string) map[string]interface{} { + var dat map[string]interface{} + _ = json.Unmarshal([]byte(data), &dat) + return dat +} + +func JsonEncode(data interface{}) (string, error) { + jsons, err := json.Marshal(data) + return string(jsons), err +} + +func JsonEncodeNoError(data interface{}) string { + jsons, _ := json.Marshal(data) + return string(jsons) +} + +func JsonDecodesNoError(data string) []string { + var dat []string + _ = json.Unmarshal([]byte(data), &dat) + return dat +} diff --git a/utils/golock/lock.go b/utils/golock/lock.go index a70e17ef..ce553085 100644 --- a/utils/golock/lock.go +++ b/utils/golock/lock.go @@ -2,9 +2,8 @@ package golock import ( "context" - "dtapps/dta/global" - "gitee.com/dtapps/go-library/utils/gouuid" - "github.com/go-redis/redis/v8" + "github.com/dtapps/go-library/utils/goredis" + "github.com/dtapps/go-library/utils/gouuid" "time" ) @@ -12,6 +11,7 @@ type lock struct { key string expiration time.Duration requestId string + Db goredis.App } func NewLock(key string, expiration time.Duration) *lock { @@ -26,7 +26,7 @@ func (lk *lock) Get() bool { defer cancel() - ok, err := global.GvaRedis.Db.SetNX(cxt, lk.key, lk.requestId, lk.expiration).Result() + ok, err := lk.Db.Db.SetNX(cxt, lk.key, lk.requestId, lk.expiration).Result() if err != nil { @@ -53,6 +53,6 @@ func (lk *lock) Release() error { script := redis.NewScript(luaScript) - _, err := script.Run(cxt, global.GvaRedis.Db, []string{lk.key}, lk.requestId).Result() + _, err := script.Run(cxt, lk.Db.Db, []string{lk.key}, lk.requestId).Result() return err } diff --git a/utils/gomac/gomac.go b/utils/gomac/gomac.go new file mode 100644 index 00000000..64e5ecb0 --- /dev/null +++ b/utils/gomac/gomac.go @@ -0,0 +1,21 @@ +package gomac + +import ( + "net" +) + +func GetMacAddrs() (macAddrs []string) { + netInterfaces, err := net.Interfaces() + if err != nil { + return macAddrs + } + for _, netInterface := range netInterfaces { + macAddr := netInterface.HardwareAddr.String() + if len(macAddr) == 0 { + continue + } + + macAddrs = append(macAddrs, macAddr) + } + return macAddrs +} diff --git a/utils/gomd5/gomd5.go b/utils/gomd5/gomd5.go new file mode 100644 index 00000000..96fbc485 --- /dev/null +++ b/utils/gomd5/gomd5.go @@ -0,0 +1,49 @@ +package gomd5 + +import ( + "crypto/md5" + "encoding/hex" + "fmt" + "io" + "strings" +) + +func Php(str string) string { + h := md5.New() + io.WriteString(h, str) + return fmt.Sprintf("%x", h.Sum(nil)) +} + +func Md5(str string) string { + s := md5.New() + s.Write([]byte(str)) + return hex.EncodeToString(s.Sum(nil)) +} + +// ToUpper md5加密后转大写 +func ToUpper(str string) string { + h := md5.New() + h.Write([]byte(str)) + cipherStr := h.Sum(nil) + return strings.ToUpper(hex.EncodeToString(cipherStr)) +} + +// ToLower md5加密后转小写 +func ToLower(str string) string { + h := md5.New() + h.Write([]byte(str)) + cipherStr := h.Sum(nil) + return strings.ToLower(hex.EncodeToString(cipherStr)) +} + +// GetMD5Encode 返回一个32位md5加密后的字符串 +func GetMD5Encode(data string) string { + h := md5.New() + h.Write([]byte(data)) + return hex.EncodeToString(h.Sum(nil)) +} + +// Get16MD5Encode 返回一个16位md5加密后的字符串 +func Get16MD5Encode(data string) string { + return GetMD5Encode(data)[8:24] +} diff --git a/utils/gomysql/app.go b/utils/gomysql/app.go index 631d5686..928c0c37 100644 --- a/utils/gomysql/app.go +++ b/utils/gomysql/app.go @@ -6,7 +6,6 @@ import ( "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" - "log" "os" "path" "time" @@ -61,8 +60,6 @@ func (w writer) Printf(format string, args ...interface{}) { func (app *App) InitClient() { - log.Printf("gomysql:%+v\n", app) - var err error if app.Log == true { @@ -89,6 +86,7 @@ func (app *App) InitClient() { if err != nil { panic(fmt.Sprintf("连接数据库服务器失败:%v", err)) } + sqlDB.SetMaxIdleConns(10) // 设置空闲连接池中连接的最大数量 sqlDB.SetMaxOpenConns(100) // 设置打开数据库连接的最大数量。 sqlDB.SetConnMaxLifetime(time.Second * 600) // 设置了连接可复用的最大时间。 diff --git a/utils/goorder/goorder.go b/utils/goorder/goorder.go new file mode 100644 index 00000000..8520ae84 --- /dev/null +++ b/utils/goorder/goorder.go @@ -0,0 +1,12 @@ +package goorder + +import ( + "fmt" + "github.com/dtapps/go-library/utils/gorandom" + "github.com/dtapps/go-library/utils/gotime" +) + +// GenerateOrDate 生成订单号 +func GenerateOrDate[T string | int | int8 | int16 | int32 | int64](customId T) string { + return fmt.Sprintf("%v%s%s", customId, gotime.Current().SetFormat("200601021504"), gorandom.Numeric(3)) +} diff --git a/utils/gophp/gophp.go b/utils/gophp/gophp.go index da479101..8f3da914 100644 --- a/utils/gophp/gophp.go +++ b/utils/gophp/gophp.go @@ -1,10 +1,8 @@ package gophp import ( - "gitee.com/dtapps/go-library/utils/gophp/serialize" + "github.com/dtapps/go-library/utils/gophp/serialize" "strconv" - "strings" - "unicode" ) // Serialize 序列 @@ -35,88 +33,3 @@ func ArrayColumn(input map[string]map[string]any, columnKey string) []any { } return columns } - -// Strtr strtr() -// -// If the parameter length is 1, type is: map[string]string -// Strtr("baab", map[string]string{"ab": "01"}) will return "ba01" -// If the parameter length is 2, type is: string, string -// Strtr("baab", "ab", "01") will return "1001", a => 0; b => 1. -func Strtr(haystack string, params ...interface{}) string { - ac := len(params) - if ac == 1 { - pairs := params[0].(map[string]string) - length := len(pairs) - if length == 0 { - return haystack - } - oldnew := make([]string, length*2) - for o, n := range pairs { - if o == "" { - return haystack - } - oldnew = append(oldnew, o, n) - } - return strings.NewReplacer(oldnew...).Replace(haystack) - } else if ac == 2 { - from := params[0].(string) - to := params[1].(string) - trlen, lt := len(from), len(to) - if trlen > lt { - trlen = lt - } - if trlen == 0 { - return haystack - } - - str := make([]uint8, len(haystack)) - var xlat [256]uint8 - var i int - var j uint8 - if trlen == 1 { - for i = 0; i < len(haystack); i++ { - if haystack[i] == from[0] { - str[i] = to[0] - } else { - str[i] = haystack[i] - } - } - return string(str) - } - // trlen != 1 - for { - xlat[j] = j - if j++; j == 0 { - break - } - } - for i = 0; i < trlen; i++ { - xlat[from[i]] = to[i] - } - for i = 0; i < len(haystack); i++ { - str[i] = xlat[haystack[i]] - } - return string(str) - } - - return haystack -} -func Rtrim(str string, characterMask ...string) string { - if len(characterMask) == 0 { - return strings.TrimRightFunc(str, unicode.IsSpace) - } - return strings.TrimRight(str, characterMask[0]) -} -func StrPad(input string, padLength int, padString string) string { - output := padString - - for padLength > len(output) { - output += output - } - - if len(input) >= padLength { - return input - } - - return output[:padLength-len(input)] + input -} diff --git a/utils/gophp/serialize/serialize.go b/utils/gophp/serialize/serialize.go index 48f2b327..856db1fd 100644 --- a/utils/gophp/serialize/serialize.go +++ b/utils/gophp/serialize/serialize.go @@ -3,7 +3,7 @@ package serialize import ( "bytes" "fmt" - "gitee.com/dtapps/go-library/utils/gostring" + "github.com/dtapps/go-library/utils/gostring" "reflect" "sort" ) diff --git a/utils/gophp/serialize/unserialize.go b/utils/gophp/serialize/unserialize.go index f9ba8743..56894f81 100644 --- a/utils/gophp/serialize/unserialize.go +++ b/utils/gophp/serialize/unserialize.go @@ -3,7 +3,7 @@ package serialize import ( "bytes" "fmt" - "gitee.com/dtapps/go-library/utils/gostring" + "github.com/dtapps/go-library/utils/gostring" "strconv" ) diff --git a/utils/gopostgresql/app.go b/utils/gopostgresql/app.go index c51ee238..5897367a 100644 --- a/utils/gopostgresql/app.go +++ b/utils/gopostgresql/app.go @@ -85,6 +85,7 @@ func (app *App) InitClient() { if err != nil { panic(fmt.Sprintf("连接数据库服务器失败:%v", err)) } + sqlDB.SetMaxIdleConns(10) // 设置空闲连接池中连接的最大数量 sqlDB.SetMaxOpenConns(100) // 设置打开数据库连接的最大数量。 sqlDB.SetConnMaxLifetime(time.Second * 600) // 设置了连接可复用的最大时间。 diff --git a/utils/gopreg/gopreg.go b/utils/gopreg/gopreg.go new file mode 100644 index 00000000..69311aad --- /dev/null +++ b/utils/gopreg/gopreg.go @@ -0,0 +1,30 @@ +package gopreg + +import ( + "regexp" +) + +// VerifyMobile 验证手机号码 +// 移动:134 135 136 137 138 139 147 150 151 152 157 158 159 178 182 183 184 187 188 198 +// 联通:130 131 132 145 155 156 166 171 175 176 185 186 +// 电信:133 149 153 173 177 180 181 189 199 +// 虚拟运营商: 170 195 +func VerifyMobile(mobile string) bool { + regular := "^[1](([3][0-9])|([4][5-9])|([5][0-3,5-9])|([6][5,6])|([7][0-8])|([8][0-9])|([9][1,5,8-9]))[0-9]{8}$" + reg := regexp.MustCompile(regular) + return reg.MatchString(mobile) +} + +// VerifyIdCard 验证身份证号码 +func VerifyIdCard(idCard string) bool { + regular := "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$|^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$" + reg := regexp.MustCompile(regular) + return reg.MatchString(idCard) +} + +// VerifyEmail 验证邮箱号码 +func VerifyEmail(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) +} diff --git a/utils/gorandom/gorandom.go b/utils/gorandom/gorandom.go new file mode 100644 index 00000000..78bac2b1 --- /dev/null +++ b/utils/gorandom/gorandom.go @@ -0,0 +1,45 @@ +package gorandom + +import ( + "math/rand" + "time" +) + +const numbers string = "0123456789" +const letters string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +const specials = "~!@#$%^*()_+-=[]{}|;:,./<>?" +const alphanumerics string = letters + numbers +const ascii string = alphanumerics + specials + +func random(n int, chars string) string { + if n <= 0 { + return "" + } + r := rand.New(rand.NewSource(time.Now().UnixNano())) + bytes := make([]byte, n, n) + l := len(chars) + for i := 0; i < n; i++ { + bytes[i] = chars[r.Intn(l)] + } + return string(bytes) +} + +// Alphanumeric 随机字母数字 +func Alphanumeric(n int) string { + return random(n, alphanumerics) +} + +// Alphabetic 随机字母 +func Alphabetic(n int) string { + return random(n, letters) +} + +// Numeric 随机数字 +func Numeric(n int) string { + return random(n, numbers) +} + +// Ascii 随机ASCII +func Ascii(n int) string { + return random(n, ascii) +} diff --git a/utils/gorsa/gorsa.go b/utils/gorsa/gorsa.go new file mode 100644 index 00000000..1bdd8d64 --- /dev/null +++ b/utils/gorsa/gorsa.go @@ -0,0 +1,77 @@ +package gorsa + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/base64" + "encoding/pem" + "os" +) + +// PublicEncrypt 公钥加密 +func PublicEncrypt(encryptStr string, path string) (string, error) { + // 打开文件 + file, err := os.Open(path) + if err != nil { + return "", err + } + defer file.Close() + + // 读取文件内容 + info, _ := file.Stat() + buf := make([]byte, info.Size()) + file.Read(buf) + + // pem 解码 + block, _ := pem.Decode(buf) + + // x509 解码 + publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + return "", err + } + + // 类型断言 + publicKey := publicKeyInterface.(*rsa.PublicKey) + + //对明文进行加密 + encryptedStr, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, []byte(encryptStr)) + if err != nil { + return "", err + } + + //返回密文 + return base64.URLEncoding.EncodeToString(encryptedStr), nil +} + +// PrivateDecrypt 私钥解密 +func PrivateDecrypt(decryptStr string, path string) (string, error) { + // 打开文件 + file, err := os.Open(path) + if err != nil { + return "", err + } + defer file.Close() + + // 获取文件内容 + info, _ := file.Stat() + buf := make([]byte, info.Size()) + file.Read(buf) + + // pem 解码 + block, _ := pem.Decode(buf) + + // X509 解码 + privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + return "", err + } + decryptBytes, err := base64.URLEncoding.DecodeString(decryptStr) + + //对密文进行解密 + decrypted, _ := rsa.DecryptPKCS1v15(rand.Reader, privateKey, decryptBytes) + + //返回明文 + return string(decrypted), nil +} diff --git a/utils/gosort/gosort.go b/utils/gosort/gosort.go new file mode 100644 index 00000000..08995af7 --- /dev/null +++ b/utils/gosort/gosort.go @@ -0,0 +1,26 @@ +package gosort + +// QuickSort 快速排序算法 +// https://www.topgoer.com/Go%E9%AB%98%E7%BA%A7/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95.html +func QuickSort(arr []int) []int { + if len(arr) <= 1 { + return arr + } + splitdata := arr[0] //第一个数据 + low := make([]int, 0, 0) //比我小的数据 + hight := make([]int, 0, 0) //比我大的数据 + mid := make([]int, 0, 0) //与我一样大的数据 + mid = append(mid, splitdata) //加入一个 + for i := 1; i < len(arr); i++ { + if arr[i] < splitdata { + low = append(low, arr[i]) + } else if arr[i] > splitdata { + hight = append(hight, arr[i]) + } else { + mid = append(mid, arr[i]) + } + } + low, hight = QuickSort(low), QuickSort(hight) + myarr := append(append(low, mid...), hight...) + return myarr +} diff --git a/utils/gossh/gossh.go b/utils/gossh/gossh.go new file mode 100644 index 00000000..26344c6f --- /dev/null +++ b/utils/gossh/gossh.go @@ -0,0 +1,66 @@ +package gossh + +import ( + "fmt" + "golang.org/x/crypto/ssh" + "io" + "net" + "time" +) + +// 转发 +func sForward(serverAddr string, remoteAddr string, localConn net.Conn, config *ssh.ClientConfig) { + // 设置sshClientConn + sshClientConn, err := ssh.Dial("tcp", serverAddr, config) + if err != nil { + fmt.Printf("ssh.Dial failed: %s", err) + } + + // 设置Connection + sshConn, err := sshClientConn.Dial("tcp", remoteAddr) + + // 将localConn.Reader复制到sshConn.Writer + go func() { + _, err = io.Copy(sshConn, localConn) + if err != nil { + fmt.Printf("io.Copy failed: %v", err) + } + }() + + // 将sshConn.Reader复制到localConn.Writer + go func() { + _, err = io.Copy(localConn, sshConn) + if err != nil { + fmt.Printf("io.Copy failed: %v", err) + } + }() +} +func Tunnel(username string, password string, serverAddr string, remoteAddr string, localAddr string) { + // 设置SSH配置 + fmt.Printf("%s,服务器:%s;远程:%s;本地:%s\n", "设置SSH配置", serverAddr, remoteAddr, localAddr) + config := &ssh.ClientConfig{ + User: username, + Auth: []ssh.AuthMethod{ + ssh.Password(password), + }, + Timeout: 30 * time.Second, + HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { + return nil + }, + } + + // 设置本地监听器 + localListener, err := net.Listen("tcp", localAddr) + if err != nil { + fmt.Printf("net.Listen failed: %v\n", err) + } + + for { + // 设置本地 + localConn, err := localListener.Accept() + if err != nil { + fmt.Printf("localListener.Accept failed: %v\n", err) + } + go sForward(serverAddr, remoteAddr, localConn, config) + } +} diff --git a/utils/gossl/gossl.go b/utils/gossl/gossl.go new file mode 100644 index 00000000..854a7c76 --- /dev/null +++ b/utils/gossl/gossl.go @@ -0,0 +1,43 @@ +package gossl + +import ( + "crypto/tls" + "errors" + "fmt" + "net/http" + "time" +) + +// https://mritd.com/2021/05/31/golang-check-certificate-expiration-time/ +func checkSSl(beforeTime time.Duration) error { + c := &http.Client{ + Transport: &http.Transport{ + // 注意如果证书已过期,那么只有在关闭证书校验的情况下链接才能建立成功 + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + }, + // 10s 超时后认为服务挂了 + Timeout: 10 * time.Second, + } + resp, err := c.Get("https://mritd.com") + if err != nil { + return err + } + defer func() { _ = resp.Body.Close() }() + + // 遍历所有证书 + for _, cert := range resp.TLS.PeerCertificates { + // 检测证书是否已经过期 + if !cert.NotAfter.After(time.Now()) { + return errors.New(fmt.Sprintf("Website [https://mritd.com] certificate has expired: %s", cert.NotAfter.Local().Format("2006-01-02 15:04:05"))) + } + + // 检测证书距离当前时间 是否小于 beforeTime + // 例如 beforeTime = 7d,那么在证书过期前 6d 开始就发出警告 + if cert.NotAfter.Sub(time.Now()) < beforeTime { + return errors.New(fmt.Sprintf("Website [https://mritd.com] certificate will expire, remaining time: %fh", cert.NotAfter.Sub(time.Now()).Hours())) + } + } + return nil +} diff --git a/utils/gotime/Tomorrow.go b/utils/gotime/Tomorrow.go new file mode 100644 index 00000000..e91268f5 --- /dev/null +++ b/utils/gotime/Tomorrow.go @@ -0,0 +1,15 @@ +package gotime + +import "time" + +// Tomorrow 明天 +func Tomorrow() Pro { + p := NewPro() + location, err := time.LoadLocation("Asia/Shanghai") + if err != nil { + p.Time = time.Now().Add(time.Hour*8).AddDate(0, 0, +1) + } else { + p.Time = time.Now().In(location).AddDate(0, 0, +1) + } + return p +} diff --git a/utils/gotime/app.go b/utils/gotime/app.go new file mode 100644 index 00000000..b10633b4 --- /dev/null +++ b/utils/gotime/app.go @@ -0,0 +1,91 @@ +package gotime + +import ( + "fmt" + "time" +) + +// 时间格式化常量 +const ( + RFC3339Format = time.RFC3339 + Iso8601Format = "2006-01-02T15:04:05-07:00" + CookieFormat = "Monday, 02-Jan-2006 15:04:05 MST" + RFC1036Format = "Mon, 02 Jan 06 15:04:05 -0700" + RFC7231Format = "Mon, 02 Jan 2006 15:04:05 GMT" + DayDateTimeFormat = "Mon, Jan 2, 2006 3:04 PM" + DateTimeFormat = "2006-01-02 15:04:05" + DateFormat = "2006-01-02" + TimeFormat = "15:04:05" + ShortDateTimeFormat = "20060102150405" + ShortDateFormat = "20060102" + ShortTimeFormat = "150405" +) + +// Pro 结构体 +type Pro struct { + Time time.Time + loc *time.Location + Error error +} + +// NewPro 初始化结构体 +func NewPro() Pro { + return Pro{ + Time: time.Now(), + } +} + +// BeforeSeconds 获取n秒前的时间 +func (p Pro) BeforeSeconds(seconds int) Pro { + st, _ := time.ParseDuration(fmt.Sprintf("-%ds", seconds)) + p.Time = p.Time.Add(st) + return p +} + +// AfterSeconds 获取n秒后的时间 +func (p Pro) AfterSeconds(seconds int) Pro { + st, _ := time.ParseDuration(fmt.Sprintf("+%ds", seconds)) + p.Time = p.Time.Add(st) + return p +} + +// BeforeHour 获取n小时前的时间 +func (p Pro) BeforeHour(hour int) Pro { + st, _ := time.ParseDuration(fmt.Sprintf("-%dh", hour)) + p.Time = p.Time.Add(st) + return p +} + +// AfterHour 获取n小时后的时间 +func (p Pro) AfterHour(hour int) Pro { + st, _ := time.ParseDuration(fmt.Sprintf("+%dh", hour)) + p.Time = p.Time.Add(st) + return p +} + +// BeforeDay 获取n天前的时间 +func (p Pro) BeforeDay(day int) Pro { + p.Time = p.Time.AddDate(0, 0, -day) + return p +} + +// AfterDay 获取n天后的时间 +func (p Pro) AfterDay(day int) Pro { + p.Time = p.Time.AddDate(0, 0, day) + return p +} + +// SetFormat 格式化 +func (p Pro) SetFormat(layout string) string { + return p.Time.Format(layout) +} + +// Month 获取当前月 +func (p Pro) Month() int { + return p.MonthOfYear() +} + +// MonthOfYear 获取本年的第几月 +func (p Pro) MonthOfYear() int { + return int(p.Time.In(p.loc).Month()) +} diff --git a/utils/gotime/differ.go b/utils/gotime/differ.go new file mode 100644 index 00000000..0ad3033e --- /dev/null +++ b/utils/gotime/differ.go @@ -0,0 +1,69 @@ +package gotime + +import "time" + +// DiffInHour 相差多少小时 +func (p Pro) DiffInHour(t2 time.Time) (hour int64) { + t2.Before(p.Time) + diff := p.Time.Unix() - t2.Unix() + hour = diff / 3600 + return hour +} + +// DiffInHourWithAbs 相差多少小时(绝对值) +func (p Pro) DiffInHourWithAbs(t2 time.Time) (hour int64) { + p.Time.Before(t2) + diff := t2.Unix() - p.Time.Unix() + hour = diff / 3600 + if hour > 0 { + return hour + } + t2.Before(p.Time) + diff = p.Time.Unix() - t2.Unix() + hour = diff / 3600 + return hour +} + +// DiffInMinutes 相差多少分钟 +func (p Pro) DiffInMinutes(t2 time.Time) (hour int64) { + t2.Before(p.Time) + diff := p.Time.Unix() - t2.Unix() + hour = diff / 60 + return hour +} + +// DiffInMinutesWithAbs 相差多少分钟(绝对值) +func (p Pro) DiffInMinutesWithAbs(t2 time.Time) (hour int64) { + p.Time.Before(t2) + diff := t2.Unix() - p.Time.Unix() + hour = diff / 60 + if hour > 0 { + return hour + } + t2.Before(p.Time) + diff = p.Time.Unix() - t2.Unix() + hour = diff / 60 + return hour +} + +// DiffInSecond 相差多少秒 +func (p Pro) DiffInSecond(t2 time.Time) (hour int64) { + t2.Before(p.Time) + diff := p.Time.Unix() - t2.Unix() + hour = diff + return hour +} + +// DiffInSecondWithAbs 相差多少秒(绝对值) +func (p Pro) DiffInSecondWithAbs(t2 time.Time) (hour int64) { + p.Time.Before(t2) + diff := t2.Unix() - p.Time.Unix() + hour = diff + if hour > 0 { + return hour + } + t2.Before(p.Time) + diff = p.Time.Unix() - t2.Unix() + hour = diff + return hour +} diff --git a/utils/gotime/errors.go b/utils/gotime/errors.go new file mode 100644 index 00000000..2f69622f --- /dev/null +++ b/utils/gotime/errors.go @@ -0,0 +1,8 @@ +package gotime + +import "fmt" + +// invalidTimezoneError 无效的时区错误 +var invalidTimezoneError = func(timezone string) error { + return fmt.Errorf("invalid timezone %q, please see the file %q for all valid timezones", timezone, "$GOROOT/lib/time/zoneinfo.zip") +} diff --git a/utils/gotime/location.go b/utils/gotime/location.go new file mode 100644 index 00000000..1b664ab0 --- /dev/null +++ b/utils/gotime/location.go @@ -0,0 +1,14 @@ +package gotime + +import ( + "time" +) + +// 通过时区获取 Location 实例 +func getLocationByTimezone(timezone string) (*time.Location, error) { + loc, err := time.LoadLocation(timezone) + if err != nil { + err = invalidTimezoneError(timezone) + } + return loc, err +} diff --git a/utils/gotime/start_end.go b/utils/gotime/start_end.go new file mode 100644 index 00000000..5afb4f50 --- /dev/null +++ b/utils/gotime/start_end.go @@ -0,0 +1,124 @@ +package gotime + +import "time" + +// 数字常量 +const ( + YearsPerMillennium = 1000 // 每千年1000年 + YearsPerCentury = 100 // 每世纪100年 + YearsPerDecade = 10 // 每十年10年 + QuartersPerYear = 4 // 每年4季度 + MonthsPerYear = 12 // 每年12月 + MonthsPerQuarter = 3 // 每季度3月 + WeeksPerNormalYear = 52 // 每常规年52周 + weeksPerLongYear = 53 // 每长年53周 + WeeksPerMonth = 4 // 每月4周 + DaysPerLeapYear = 366 // 每闰年366天 + DaysPerNormalYear = 365 // 每常规年365天 + DaysPerWeek = 7 // 每周7天 + HoursPerWeek = 168 // 每周168小时 + HoursPerDay = 24 // 每天24小时 + MinutesPerDay = 1440 // 每天1440分钟 + MinutesPerHour = 60 // 每小时60分钟 + SecondsPerWeek = 604800 // 每周604800秒 + SecondsPerDay = 86400 // 每天86400秒 + SecondsPerHour = 3600 // 每小时3600秒 + SecondsPerMinute = 60 // 每分钟60秒 + MillisecondsPerSecond = 1000 // 每秒1000毫秒 + MicrosecondsPerMillisecond = 1000 // 每毫秒1000微秒 + MicrosecondsPerSecond = 1000000 // 每秒1000000微秒 +) + +// StartOfCentury 本世纪开始时间 +func (p Pro) StartOfCentury() Pro { + p.Time = time.Date(p.Time.Year()/YearsPerCentury*YearsPerCentury, 1, 1, 0, 0, 0, 0, p.Time.Location()) + return p +} + +// EndOfCentury 本世纪结束时间 +func (p Pro) EndOfCentury() Pro { + p.Time = time.Date(p.Time.Year()/YearsPerCentury*YearsPerCentury+99, 12, 31, 23, 59, 59, 999999999, p.Time.Location()) + return p +} + +// StartOfDecade 本年代开始时间 +func (p Pro) StartOfDecade() Pro { + p.Time = time.Date(p.Time.Year()/YearsPerDecade*YearsPerDecade, 1, 1, 0, 0, 0, 0, p.Time.Location()) + return p +} + +// EndOfDecade 本年代结束时间 +func (p Pro) EndOfDecade() Pro { + p.Time = time.Date(p.Time.Year()/YearsPerDecade*YearsPerDecade+9, 12, 31, 23, 59, 59, 999999999, p.Time.Location()) + return p +} + +// StartOfYear 本年开始时间 +func (p Pro) StartOfYear() Pro { + p.Time = time.Date(p.Time.Year(), 1, 1, 0, 0, 0, 0, p.Time.Location()) + return p +} + +// EndOfYear 本年结束时间 +func (p Pro) EndOfYear() Pro { + p.Time = time.Date(p.Time.Year(), 12, 31, 23, 59, 59, 999999999, p.Time.Location()) + return p +} + +// Quarter 获取当前季度 +func (p Pro) Quarter() (quarter int) { + switch { + case p.Time.Month() >= 10: + quarter = 4 + case p.Time.Month() >= 7: + quarter = 3 + case p.Time.Month() >= 4: + quarter = 2 + case p.Time.Month() >= 1: + quarter = 1 + } + return +} + +// StartOfQuarter 本季度开始时间 +func (p Pro) StartOfQuarter() Pro { + p.Time = time.Date(p.Time.Year(), time.Month(3*p.Quarter()-2), 1, 0, 0, 0, 0, p.Time.Location()) + return p +} + +// EndOfQuarter 本季度结束时间 +func (p Pro) EndOfQuarter() Pro { + quarter, day := p.Quarter(), 30 + switch quarter { + case 1, 4: + day = 31 + case 2, 3: + day = 30 + } + p.Time = time.Date(p.Time.Year(), time.Month(3*quarter), day, 23, 59, 59, 999999999, p.Time.Location()) + return p +} + +// StartOfMonth 本月开始时间 +func (p Pro) StartOfMonth() Pro { + p.Time = time.Date(p.Time.Year(), time.Month(p.Month()), 1, 0, 0, 0, 0, p.Time.Location()) + return p +} + +// EndOfMonth 本月结束时间 +func (p Pro) EndOfMonth() Pro { + p.Time = time.Date(p.Time.Year(), time.Month(p.Month()), 1, 23, 59, 59, 999999999, p.Time.Location()) + return p +} + +// StartOfDay 本日开始时间 +func (p Pro) StartOfDay() Pro { + p.Time = time.Date(p.Time.Year(), p.Time.Month(), p.Time.Day(), 0, 0, 0, 0, p.Time.Location()) + return p +} + +// EndOfDay 本日结束时间 +func (p Pro) EndOfDay() Pro { + p.Time = time.Date(p.Time.Year(), p.Time.Month(), p.Time.Day(), 23, 59, 59, 0, p.Time.Location()) + return p +} diff --git a/utils/gotime/today.go b/utils/gotime/today.go new file mode 100644 index 00000000..f19f505e --- /dev/null +++ b/utils/gotime/today.go @@ -0,0 +1,112 @@ +package gotime + +import ( + "log" + "strconv" + "strings" + "time" +) + +// Current 获取当前的时间 +func Current() Pro { + p := NewPro() + p.loc, p.Error = time.LoadLocation("Asia/Shanghai") + if p.Error != nil { + // Docker部署golang应用时时区问题 https://www.ddhigh.com/2018/03/01/golang-docker-timezone.html + log.Printf("【gotime】时区错误:%v\n", p.Error) + p.Time = time.Now().Add(time.Hour * 8) + } else { + p.Time = time.Now().In(p.loc) + } + return p +} + +// SetCurrent 设置当前的时间 +func SetCurrent(sTime time.Time) Pro { + p := NewPro() + p.Time = sTime + return p +} + +// SetCurrentParse 设置当前的时间 +func SetCurrentParse(str string) Pro { + + p := NewPro() + + p.loc, p.Error = time.LoadLocation("Asia/Shanghai") + + layout := DateTimeFormat + if str == "" || str == "0" || str == "0000-00-00 00:00:00" || str == "0000-00-00" || str == "00:00:00" { + return p + } + if len(str) == 10 && strings.Count(str, "-") == 2 { + layout = DateFormat + } + if strings.Index(str, "T") == 10 { + layout = RFC3339Format + } + if _, err := strconv.ParseInt(str, 10, 64); err == nil { + switch len(str) { + case 8: + layout = ShortDateFormat + case 14: + layout = ShortDateTimeFormat + } + } + location, _ := time.ParseInLocation(layout, str, p.loc) + + p.Time = location + return p +} + +// SetCurrentUnix 设置当前的时间 Unix时间戳 +func SetCurrentUnix(ts int64) Pro { + p := NewPro() + p.Time = time.Unix(ts, 0) + return p +} + +// Now 今天此刻 +func (p Pro) Now() time.Time { + return p.Time +} + +// Format 今天此刻格式化 +func (p Pro) Format() string { + return p.Time.Format(DateTimeFormat) +} + +// ToDateFormat 今天此刻日期 +func (p Pro) ToDateFormat() string { + return p.Time.Format(DateFormat) +} + +// ToTimeFormat 今天此刻时间 +func (p Pro) ToTimeFormat() string { + return p.Time.Format(TimeFormat) +} + +// Timestamp 今天此刻时间戳 +func (p Pro) Timestamp() int64 { + return p.Time.Unix() +} + +// TimestampWithSecond 今天此刻时间戳 +func (p Pro) TimestampWithSecond() int64 { + return p.Time.Unix() +} + +// TimestampWithMillisecond 今天毫秒级时间戳 +func (p Pro) TimestampWithMillisecond() int64 { + return p.Time.UnixNano() / int64(time.Millisecond) +} + +// TimestampWithMicrosecond 今天微秒级时间戳 +func (p Pro) TimestampWithMicrosecond() int64 { + return p.Time.UnixNano() / int64(time.Microsecond) +} + +// TimestampWithNanosecond 今天纳秒级时间戳 +func (p Pro) TimestampWithNanosecond() int64 { + return p.Time.UnixNano() +} diff --git a/utils/gotime/yesterday.go b/utils/gotime/yesterday.go new file mode 100644 index 00000000..be1cd6c6 --- /dev/null +++ b/utils/gotime/yesterday.go @@ -0,0 +1,17 @@ +package gotime + +import ( + "time" +) + +// Yesterday 昨天 +func Yesterday() Pro { + p := NewPro() + location, err := time.LoadLocation("Asia/Shanghai") + if err != nil { + p.Time = time.Now().Add(time.Hour*8).AddDate(0, 0, -1) + } else { + p.Time = time.Now().In(location).AddDate(0, 0, -1) + } + return p +} diff --git a/utils/gouuid/gouuid.go b/utils/gouuid/gouuid.go new file mode 100644 index 00000000..754fee6b --- /dev/null +++ b/utils/gouuid/gouuid.go @@ -0,0 +1,18 @@ +package gouuid + +import ( + "crypto/rand" + "fmt" + "time" +) + +// GetUuId 获取唯一ID +func GetUuId() string { + unix32bits := uint32(time.Now().UTC().Unix()) + buff := make([]byte, 12) + numRead, err := rand.Read(buff) + if numRead != len(buff) || err != nil { + return "" + } + return fmt.Sprintf("%x-%x-%x-%x-%x-%x", unix32bits, buff[0:2], buff[2:4], buff[4:6], buff[6:8], buff[8:]) +} diff --git a/utils/phpjson/phpjson.go b/utils/phpjson/phpjson.go new file mode 100644 index 00000000..16d8eafa --- /dev/null +++ b/utils/phpjson/phpjson.go @@ -0,0 +1,50 @@ +package phpjson + +import ( + "encoding/json" + "fmt" + "reflect" + "strings" +) + +func Encode(v interface{}) (string, error) { + bytes, err := json.Marshal(v) + if err != nil { + return "", err + } + return string(bytes), nil +} + +func MarshalToString(msg interface{}) (string, error) { + j, e := json.Marshal(msg) + if e != nil { + return "", e + } + return string(j), nil +} + +func Implode(list interface{}, seq string) string { + listValue := reflect.Indirect(reflect.ValueOf(list)) + if listValue.Kind() != reflect.Slice { + return "" + } + count := listValue.Len() + listStr := make([]string, 0, count) + for i := 0; i < count; i++ { + v := listValue.Index(i) + if str, err := getValue(v); err == nil { + listStr = append(listStr, str) + } + } + return strings.Join(listStr, seq) +} + +func getValue(value reflect.Value) (res string, err error) { + switch value.Kind() { + case reflect.Ptr: + res, err = getValue(value.Elem()) + default: + res = fmt.Sprint(value.Interface()) + } + return +}