38 Commits

Author SHA1 Message Date
  gz 1451ae0148 修改GetDomain 2 weeks ago
  guzeng c824e5a723 增加MAP合并方法 5 months ago
  guzeng 814bdf7d29 增加雪花算法实现方法 8 months ago
  guzeng 4afc8e0f8f 修改字符转换 9 months ago
  guzeng 0506319ef0 增加MAP索引转大驼峰 1 year ago
  lijianbin 3c78cdcc34 增加数字型字符切片排序函数 1 year ago
  loshiqi a18c222878 map切片把for改成截取 1 year ago
  loshiqi 94dc6d70d3 增加map切片排序 1 year ago
  loshiqi 3eb178421d map切片排序需增加排序值类型 1 year ago
  loshiqi 4b5435e039 增加map切片值顺序排序 1 year ago
  lijianbin 86f28b9b83 过滤日志 1 year ago
  lijianbin a28b3cd384 增加招行支付通用函数库 1 year ago
  lijianbin e321c06f25 增加招行支付通用函数库 1 year ago
  guzeng 52462da6b4 增加十进制转十六进制方法 1 year ago
  guzeng be3c84d62c 修改获取本地时间 2 years ago
  lijianbin 58bcbf5220 增加当天结束时间函数 2 years ago
  lijianbin 7128e60789 增加具体日期转时间戳函数 2 years ago
  lijianbin 90f69f2c81 增加具体日期转时间戳函数 2 years ago
  yangzm 0d5aa7b020 Merge branch 'master' of https://git.tetele.net/tgo/helper 2 years ago
  yangzm c195bf7819 【杨】增加结构体操作 2 years ago
  listen a200850a57 加入interface转map[string]string 2 years ago
  yangzm 4f8a7b43df 【杨】增加切片去重 2 years ago
  yangzm 54c1b62e8b 【杨】增加切片差集&交集&并集 2 years ago
  listen fb5a0d87c4 更新方法 2 years ago
  listen c02fce39fb 加入区间随机数 2 years ago
  listen 1759dab127 加入操作map的方法 2 years ago
  listen fe05110b1e Merge branch 'master' of https://git.tetele.net/tgo/helper 2 years ago
  listen 11e307358a 加入interfce转map方法 2 years ago
  guzeng 0eb2d1bac9 Merge branch 'master' of ssh://git.tetele.net:4001/tgo/helper 2 years ago
  guzeng 173222ae49 增加RFC3339时间转换 2 years ago
  listen 1a69548286 加入过滤html标签方法 2 years ago
  wuyongyuan a2aaf6a7b9 修改HttpBuildStringQuery方法 2 years ago
  wuyongyuan acb19ca55c Merge branch 'master' of https://git.tetele.net/tgo/helper 2 years ago
  wuyongyuan e4f8672814 新增返回字符串在切片中对应索引和不进行排序map字典拼接 2 years ago
  guzeng c944b89b55 Merge branch 'master' of ssh://git.tetele.net:4001/tgo/helper 2 years ago
  guzeng 6559db4b47 修改驼峰转换 2 years ago
  listen ec4eb3f122 加入本月开始时间戳方法 2 years ago
  listen 0d726b8da2 加入获取当天开始时间戳方法 2 years ago
21 changed files with 1377 additions and 14 deletions
Split View
  1. +387
    -0
      cmb.go
  2. +7
    -0
      go.mod
  3. +28
    -0
      go.sum
  4. +1
    -1
      header.go
  5. +199
    -0
      map.go
  6. +26
    -2
      map_test.go
  7. +38
    -0
      math.go
  8. +15
    -0
      math_test.go
  9. +44
    -0
      rand.go
  10. +115
    -0
      slice.go
  11. +41
    -0
      slice_test.go
  12. +62
    -0
      snowflake.go
  13. +16
    -0
      snowflake_test.go
  14. +57
    -2
      string.go
  15. +15
    -1
      string_test.go
  16. +149
    -0
      struct.go
  17. +47
    -0
      struct_test.go
  18. +0
    -0
      system.go
  19. +80
    -0
      time.go
  20. +38
    -8
      time_test.go
  21. +12
    -0
      uuid_test.go

+ 387
- 0
cmb.go View File

@ -0,0 +1,387 @@
package helper
import (
"bytes"
"encoding/base64"
"encoding/hex"
"errors"
"git.tetele.net/tgo/crypter"
"github.com/ZZMarquis/gm/sm2"
"github.com/ZZMarquis/gm/sm3"
jsoniter "github.com/json-iterator/go"
"io/ioutil"
"log"
"math/big"
"net/http"
"reflect"
"sort"
"strings"
"time"
)
var json = jsoniter.ConfigCompatibleWithStandardLibrary
// 合并map数据
func MergeMapData(x, y map[string]interface{}) map[string]interface{} {
n := make(map[string]interface{})
for i, v := range x {
for j, w := range y {
if i == j {
n[i] = w
} else {
if _, ok := n[i]; !ok {
n[i] = v
}
if _, ok := n[j]; !ok {
n[j] = w
}
}
}
}
return n
}
// 针对传参为json或者数组类型的字段,进行字符串排序
func HttpBuildSort(data map[string]interface{}) string {
keySlice := []string{}
for k, _ := range data {
keySlice = append(keySlice, k)
}
// 排序字符串
sort.Strings(keySlice)
res := make(map[string]interface{}, 0)
for _, value := range keySlice {
data_val := ToStr(data[value])
if value != "" && data_val != "" {
res[value] = data_val
}
}
res_byte, _ := json.Marshal(res)
return string(res_byte)
}
// body参数处理
func FormatBodyData(body map[string]interface{}) map[string]interface{} {
data := map[string]interface{}{}
if len(body) > 0 {
for k, v := range body {
typeOfA := reflect.TypeOf(v)
if typeOfA.Kind().String() == "map" {
build_str_format, _ := InterfaceToMapInterface(v)
if len(build_str_format) < 1 {
continue
}
// json键值对处理
data[k] = HttpBuildSort(build_str_format)
// log.Println("排序后的数据: ", data[k])
} else if typeOfA.Kind().String() == "slice" {
val_slice := []interface{}{}
// json键值对处理
for _, val_inter := range v.([]interface{}) {
val_map, _ := InterfaceToMapInterface(val_inter)
each_val := HttpBuildSort(val_map)
val_slice = append(val_slice, each_val)
}
if len(val_slice) < 1 {
continue
}
data[k] = val_slice
// log.Println("排序后的数据: ", data[k])
} else {
data[k] = v
}
}
}
return data
}
// 字符串排序拼接
func CmbHttpBuildQuery(data map[string]interface{}, filter_sign bool) string {
keySlice := []string{}
// 剔除sign字段
for k, _ := range data {
if filter_sign && k == "sign" {
continue
}
keySlice = append(keySlice, k)
}
// 排序字符串
sort.Strings(keySlice)
var query string
for _, value := range keySlice {
if value != "" && data[value] != "" {
query += StringJoin(value, "=", ToStr(data[value]), "&")
}
}
build_str := strings.Trim(query, "&")
return build_str
}
// 生成签名sign--聚合支付
func SetSign(data map[string]interface{}, privateKey string) string {
build_str := CmbHttpBuildQuery(data, true)
priv := new(sm2.PrivateKey)
priv.Curve = sm2.GetSm2P256V1()
dBytes, _ := hex.DecodeString(privateKey)
priv.D = new(big.Int).SetBytes(dBytes)
signature, err := sm2.Sign(priv, []byte("1234567812345678"), []byte(build_str))
if err != nil {
log.Println("国密加密异常", err)
return ""
}
sign := base64.StdEncoding.EncodeToString(signature)
return sign
}
// 创建请求头信息--聚合支付
func HeaderInfo(appid, secret, sign string) map[string]string {
if appid == "" || secret == "" || sign == "" {
return map[string]string{}
}
headerData := map[string]string{}
headerData["appid"] = appid
headerData["sign"] = sign
headerData["secret"] = secret
headerData["timestamp"] = ToStr(time.Now().Unix())
build_str := CmbHttpBuildQuery(MapStringToInterface(headerData), false)
headerData["apisign"] = crypter.Md5Str(build_str)
delete(headerData, "sign")
delete(headerData, "secret")
return headerData
}
// 接口验签--各客户端请求我们接口验签
func CheckSign(appid, app_secret, timeStamp, nonce, sign string, body map[string]interface{}) error {
/*time_now := time.Now().Unix()
if time_now-ToInt64(timeStamp) > 10 {
return errors.New("请求时间超出范围,拒绝访问")
}*/
sign_info := map[string]interface{}{
"appid": appid,
"timestamp": timeStamp,
"nonce": nonce,
}
if len(body) > 0 {
body_format := FormatBodyDataNoList(body)
sign_info = MergeMapData(sign_info, body_format)
}
str := CmbHttpBuildQuery(sign_info, false) + "&" + app_secret
sign_str := crypter.Md5Str(str)
if sign_str != sign {
return errors.New("签名不正确")
}
return nil
}
// post 请求
func PostJsonData(url string, param interface{}, headerinfo map[string]string) ([]byte, error) {
httpClient := &http.Client{}
params, err := json.Marshal(param)
if err != nil {
return []byte(""), err
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(params))
if err != nil {
return []byte(""), err
}
req.Header.Set("Content-Type", "application/json")
if len(headerinfo) > 0 {
for k, v := range headerinfo {
req.Header[k] = []string{v}
}
}
resp, err := httpClient.Do(req)
if err != nil {
return []byte(""), err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return []byte(""), err
}
return body, nil
}
func SetSignsm3(data map[string]interface{}) string {
build_str := HttpBuildjson(data, false)
h := sm3.New()
h.Write([]byte(build_str))
sum := h.Sum(nil)
sign := hex.EncodeToString(sum)
return sign
}
func CashierHeaderInfoCompany(appid, secret, sign, private_key string) map[string]string {
if appid == "" || secret == "" || sign == "" || private_key == "" {
return map[string]string{}
}
headerData := map[string]string{}
headerData["appid"] = appid
headerData["sign"] = sign
headerData["secret"] = secret
headerData["timestamp"] = ToStr(time.Now().Unix())
headerData["apisign"] = SetSignhex(headerData, private_key)
headerData["verify"] = "SM3withSM2"
delete(headerData, "secret")
return headerData
}
// 生成签名sign
func SetSignhex(data map[string]string, privateKey string) string {
build_str := CmbHttpBuildQuery(MapStringToInterface(data), false)
priv := new(sm2.PrivateKey)
priv.Curve = sm2.GetSm2P256V1()
dBytes, _ := hex.DecodeString(privateKey)
priv.D = new(big.Int).SetBytes(dBytes)
sign, _ := sm2.Sign(priv, []byte("1234567812345678"), []byte(build_str))
sign = SM2Asn1ToRaw(sign)
return hex.EncodeToString(sign)
}
func SM2Asn1ToRaw(data []byte) []byte {
i := 3
ret := []byte{}
if data[i] == 32 {
i = i + 1
} else if data[i] == 33 {
i = i + 2
}
for k := 0; k < 32; k++ {
ret = append(ret, data[i+k])
}
i = i + 32
i = i + 1
if data[i] == 32 {
i = i + 1
} else if data[i] == 33 {
i = i + 2
}
for k := 0; k < 32; k++ {
ret = append(ret, data[i+k])
}
return ret
}
// 字符串排序拼接
func HttpBuildjson(data map[string]interface{}, filter_sign bool) string {
keySlice := []string{}
res := map[string]interface{}{}
// 剔除sign字段
for k, _ := range data {
if filter_sign && k == "sign" {
continue
}
keySlice = append(keySlice, k)
}
// 排序字符串
sort.Strings(keySlice)
for _, value := range keySlice {
if value != "" && data[value] != "" {
res[value] = data[value]
}
}
ss, _ := json.Marshal(res)
return string(ss)
}
// body参数处理
func FormatBodyDataNoList(body map[string]interface{}) map[string]interface{} {
data := map[string]interface{}{}
if len(body) > 0 {
for k, v := range body {
typeOfA := reflect.TypeOf(v)
if typeOfA.Kind().String() == "map" || typeOfA.Kind().String() == "slice" {
continue
} else {
if typeOfA.Kind().String() == "string" {
if ToStr(v) != "" {
data[k] = v
}
}
}
}
}
return data
}
// 聚合支付异步回调验签
func JhNotifyCheckSign(sign, public_key string, data map[string]string) bool {
build_sort_str := CmbHttpBuildQuery(MapStringToInterface(data), true)
pub_x := ""
pub_y := ""
// 私钥截取
if len(public_key) == 128 {
pub_x = public_key[:64]
pub_y = public_key[64:]
} else if len(public_key) == 130 && (public_key[:2] == "04") {
public_key = public_key[2:]
pub_x = public_key[:64]
pub_y = public_key[64:]
} else {
log.Println("异步验签公钥出错", public_key)
return false
}
sign_b64, _ := base64.StdEncoding.DecodeString(sign)
pub := new(sm2.PublicKey)
pub.Curve = sm2.GetSm2P256V1()
xBytes, _ := hex.DecodeString(pub_x)
yBytes, _ := hex.DecodeString(pub_y)
pub.X = new(big.Int).SetBytes(xBytes)
pub.Y = new(big.Int).SetBytes(yBytes)
result := sm2.Verify(pub, []byte("1234567812345678"), []byte(build_sort_str), sign_b64)
if !result {
return false
}
return true
}

+ 7
- 0
go.mod View File

@ -1,3 +1,10 @@
module git.tetele.net/tgo/helper
go 1.14
require (
git.tetele.net/tgo/crypter v0.2.2
github.com/ZZMarquis/gm v1.3.2
github.com/json-iterator/go v1.1.12
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
)

+ 28
- 0
go.sum View File

@ -0,0 +1,28 @@
git.tetele.net/tgo/crypter v0.2.2 h1:YMQJh2Gj5Po4ZfelJUmXBKi01UbmtiSy3bmqRfnYQMo=
git.tetele.net/tgo/crypter v0.2.2/go.mod h1:vfvRLZA8+lHNgNXneOcgvVhDyuv25ZRb+C6xHOmXNx0=
github.com/ZZMarquis/gm v1.3.2 h1:lFtpzg5zeeVMZ/gKi0gtYcKLBEo9XTqsZDHDz6s3Gow=
github.com/ZZMarquis/gm v1.3.2/go.mod h1:wWbjZYgruQVd7Bb8UkSN8ujU931kx2XUW6nZLCiDE0Q=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

+ 1
- 1
header.go View File

@ -44,7 +44,7 @@ func GetDomain(req *http.Request) string {
var host string = GetHost(req)
hosts := strings.Split(host, ":")
host = hosts[0]
if hosts[1] == "443" {
if len(hosts) > 1 && hosts[1] == "443" {
scheme = "https://"
}
var w strings.Builder


+ 199
- 0
map.go View File

@ -2,6 +2,7 @@ package helper
import (
"errors"
"net/url"
"sort"
"strings"
)
@ -94,6 +95,62 @@ func MapStringToInterface(src map[string]string) map[string]interface{} {
return target
}
// 将interface转成map[string]interface
func InterfaceToMapInterface(data interface{}) (map[string]interface{}, error) {
dataJson, err := json.Marshal(data)
if err != nil {
return nil, err
}
var returnData map[string]interface{}
err = json.Unmarshal(dataJson, &returnData)
return returnData, nil
}
// 将interface转成map[string]string
func InterfaceToMapString(data interface{}) (map[string]string, error) {
dataJson, err := json.Marshal(data)
if err != nil {
return nil, err
}
var returnData map[string]string
err = json.Unmarshal(dataJson, &returnData)
return returnData, nil
}
// 将interface转成[]map[string]interface
func InterfaceToMapInterfaceArr(data interface{}) ([]map[string]interface{}, error) {
dataJson, err := json.Marshal(data)
if err != nil {
return nil, err
}
var returnData []map[string]interface{}
err = json.Unmarshal(dataJson, &returnData)
return returnData, nil
}
// 将interface转成[]map[string]string
func InterfaceToMapStringArr(data interface{}) ([]map[string]string, error) {
dataJson, err := json.Marshal(data)
if err != nil {
return nil, err
}
var returnData []map[string]string
err = json.Unmarshal(dataJson, &returnData)
return returnData, nil
}
/**
* 对map进行字典序排序
* @param data map[string]string
@ -119,3 +176,145 @@ func HttpBuildQuery(data map[string]string) string {
return strings.Trim(query, "&")
}
/**
* 对map字典按照顺序进行拼接并且把每个value进行类urlencode
* @param data map[string]string
* @2021/10/14
* @wyy
*/
func HttpBuildStringQuery(data map[string]string) string {
keySlice := []string{}
for k, _ := range data {
keySlice = append(keySlice, k)
}
// sort.Strings(keySlice) //排序字符串
var query string
for _, value := range keySlice {
if value != "" && data[value] != "" {
query += StringJoin(value, "=", url.QueryEscape(data[value]), "&")
}
}
return strings.Trim(query, "&")
}
/**
* 对map切片 按值进行顺序
* @param order desc/asc val_type float64/string MapDate []map[string]interface{}
* @2022/10/27
* @lo
*/
func MapSort(order, val, val_type string, MapDate []map[string]interface{}) ([]map[string]interface{}, error) {
type KVPair struct {
Key int
Val_float64 float64
val_string string
}
res := []map[string]interface{}{}
if order != "desc" && order != "asc" {
return res, errors.New("order parameter err")
}
if val_type != "float64" && val_type != "string" {
return res, errors.New("val_type parameter err")
}
if val == "" {
return res, errors.New("val parameter err")
}
if len(MapDate) < 1 {
return res, errors.New("MapDate parameter err")
}
tmpList := []KVPair{}
if val_type == "string" {
for k, item := range MapDate {
tmpList = append(tmpList, KVPair{Key: k, val_string: ToStr(item[val])})
}
if order == "desc" {
sort.Slice(tmpList, func(i, j int) bool {
return tmpList[i].val_string > tmpList[j].val_string // 降序
})
} else {
sort.Slice(tmpList, func(i, j int) bool {
return tmpList[i].val_string < tmpList[j].val_string // 升序
})
}
} else {
for k, item := range MapDate {
float64_val, _ := ToFloat64(item[val])
tmpList = append(tmpList, KVPair{Key: k, Val_float64: float64_val})
}
if order == "desc" {
sort.Slice(tmpList, func(i, j int) bool {
return tmpList[i].Val_float64 > tmpList[j].Val_float64 // 降序
})
} else {
sort.Slice(tmpList, func(i, j int) bool {
return tmpList[i].Val_float64 < tmpList[j].Val_float64 // 升序
})
}
}
for _, tmp := range tmpList {
res = append(res, MapDate[tmp.Key])
}
return res, nil
}
func MapPage(pageNum, pageSize int, MapDate []map[string]interface{}) []map[string]interface{} {
stat := (pageNum - 1) * pageSize
end := stat + pageSize
count := len(MapDate)
if stat >= count {
return []map[string]interface{}{}
}
if end >= count {
end = count
}
if stat < 0 || end < 0 {
return []map[string]interface{}{}
}
return MapDate[stat:end]
}
/**
* MAP索引转大驼峰
* gz
*/
func SetMapFirstToUpper(info map[string]interface{}) map[string]interface{} {
var ret map[string]interface{}
if len(info) > 0 {
ret = make(map[string]interface{})
for k, v := range info {
ret[StrFirstToUpper(k)] = v
}
}
return ret
}
/**
* MAP合并相同KEY以最后一个为准
* gz 2023/11/13
*/
func MergeMaps(map1 map[string]string, map2 ...map[string]string) map[string]string {
mergedMap := make(map[string]string)
if len(map1) > 0 {
for key, value := range map1 {
mergedMap[key] = value
}
}
if len(map2) > 0 {
for _, arr := range map2 {
if len(arr) > 0 {
for key, value := range arr {
mergedMap[key] = value //以后个为准
}
}
}
}
return mergedMap
}

+ 26
- 2
map_test.go View File

@ -6,10 +6,34 @@ import (
func Test_HttpBuildQuery(t *testing.T) {
list := map[string]string{"a": "b", "": "cdd", "b": ""}
a := map[string]interface{}{"id": "11", "name": "8", "price": "2.3"}
b := map[string]interface{}{"id": "4", "name": "7", "price": "2.8"}
c := map[string]interface{}{"id": "3", "name": "9", "price": "2.1"}
list := []map[string]interface{}{}
list = append(list, a)
list = append(list, b)
list = append(list, c)
//ret := HttpBuildQuery(list)
ret, err := MapSort("desc", "id", "float64", list)
ret := HttpBuildQuery(list)
if err != nil {
}
t.Log(ret)
}
func Test_SetMapFirstToUpper(t *testing.T) {
a := map[string]interface{}{"id": "11", "name": "8", "a_c": 99, "price": "2.3", "cc_dd_ee": 22}
ret := SetMapFirstToUpper(a)
t.Log(ret)
}
func Test_MergeMaps(t *testing.T) {
a := map[string]string{"a": "1", "b": "2", "c": "3"}
b := map[string]string{"e": "5", "f": "6", "g": "7"}
// c := map[string]string{"a": "0", "h": "8", "f": "10"}
ret := MergeMaps(a, b)
t.Log(ret)
}

+ 38
- 0
math.go View File

@ -4,6 +4,7 @@ import (
"fmt"
"math/big"
"strconv"
"strings"
)
//字节自动转换为B/KB/MB/GB
@ -129,3 +130,40 @@ func FloatQuo(str ...interface{}) float64 {
ret, _ = strconv.ParseFloat(fmt.Sprintf("%."+places+"f", ret), 64)
return ret
}
/**
* 十进制转十六进制
*/
func DecToHex(ten int) string {
m := 0
hex := make([]int, 0)
for {
m = ten % 16
ten = ten / 16
if ten == 0 {
hex = append(hex, m)
break
}
hex = append(hex, m)
}
hexStr := []string{}
for i := len(hex) - 1; i >= 0; i-- {
if hex[i] >= 10 {
hexStr = append(hexStr, fmt.Sprintf("%c", 'A'+hex[i]-10))
} else {
hexStr = append(hexStr, fmt.Sprintf("%d", hex[i]))
}
}
return strings.Join(hexStr, "")
}
/**
* 十六进制转十进制
*/
func HexToDec(val string) (int, error) {
n, err := strconv.ParseUint(val, 16, 64)
if err != nil {
return 0, err
}
return int(n), nil
}

+ 15
- 0
math_test.go View File

@ -1,6 +1,7 @@
package helper
import (
"math"
"strings"
"testing"
)
@ -41,4 +42,18 @@ func Test_FloatQuo(t *testing.T) {
str2 := "7"
ret := FloatQuo(str1, str2, 3)
t.Log(ret)
ret = math.Ceil(FloatQuo(4500, 3600))
t.Log(ret)
}
// func Test_TenToHex(t *testing.T) {
// str1 := 10664
// ret := TenToHex(str1)
// t.Log(ret)
// }
// func Test_HexToTen(t *testing.T) {
// str := "29B79F0D"
// ret, err := HexToTen(str)
// t.Log(ret, err)
// }

+ 44
- 0
rand.go View File

@ -0,0 +1,44 @@
package helper
import (
"crypto/rand"
"math/big"
)
/**
* 获取int类型的区间随机数
*/
func GetRandInt(min, max int) (r int, err error) {
_r, err := GetRandInt64(int64(min), int64(max))
if err != nil {
return
}
r = int(_r)
return
}
/**
* 获取int64类型的区间随机数
*/
func GetRandInt64(min, max int64) (r int64, err error) {
if min == max {
r = min
return
}
if min > max {
max, min = min, max
}
result, err := rand.Int(rand.Reader, big.NewInt(max-min))
if err != nil {
return
}
r = result.Int64() + min
b, err := rand.Int(rand.Reader, big.NewInt(2))
if err == nil && b.Int64() == 1 {
r += 1
}
return
}

+ 115
- 0
slice.go View File

@ -0,0 +1,115 @@
/*
* string functions
*/
package helper
import (
"errors"
"fmt"
"sort"
)
// 求差集
func Diff(slice1, slice2 []string) []string {
m := make(map[string]int)
nn := make([]string, 0)
inter := Intersect(slice1, slice2)
for _, v := range inter {
m[v]++
}
for _, value := range slice1 {
times, _ := m[value]
if times == 0 {
nn = append(nn, value)
}
}
return nn
}
// 求交集
func Intersect(slice1, slice2 []string) []string {
m := make(map[string]int)
nn := make([]string, 0)
for _, v := range slice1 {
m[v]++
}
for _, v := range slice2 {
times, _ := m[v]
if times == 1 {
nn = append(nn, v)
}
}
return nn
}
// 求并集
func Union(slice1, slice2 []string) []string {
m := make(map[string]int)
for _, v := range slice1 {
m[v]++
}
for _, v := range slice2 {
times, _ := m[v]
if times == 0 {
slice1 = append(slice1, v)
}
}
return slice1
}
func Unique(originals interface{}) (interface{}, error) {
temp := map[string]struct{}{}
switch slice := originals.(type) {
case []string:
result := make([]string, 0, len(originals.([]string)))
for _, item := range slice {
key := fmt.Sprint(item)
if _, ok := temp[key]; !ok {
temp[key] = struct{}{}
result = append(result, item)
}
}
return result, nil
case []int64:
result := make([]int64, 0, len(originals.([]int64)))
for _, item := range slice {
key := fmt.Sprint(item)
if _, ok := temp[key]; !ok {
temp[key] = struct{}{}
result = append(result, item)
}
}
return result, nil
default:
return nil, errors.New(fmt.Sprintf("Unknown type: %T", slice))
}
}
// 将切片字符串(数字型)排序
func StringSliceSort(str []string, sort_type string) ([]string, error) {
int_arr := []int{}
string_arr := []string{}
if len(str) < 1 {
return []string{}, nil
}
for _, val := range str {
int_arr = append(int_arr, ToInt(val))
}
if sort_type == "desc" {
sort.Sort(sort.Reverse(sort.IntSlice(int_arr)))
}else{
sort.Ints(int_arr)
}
for _, val_int := range int_arr {
string_arr = append(string_arr, ToStr(val_int))
}
return string_arr, nil
}

+ 41
- 0
slice_test.go View File

@ -0,0 +1,41 @@
package helper
import (
"fmt"
"testing"
)
func Test_Diff(t *testing.T) {
var aa = []string{"43", "33"}
var bb = []string{"2", "33", "1"}
cc := Diff(aa, bb)
fmt.Println(cc)
}
func Test_Intersect(t *testing.T) {
var aa = []string{"43", "33"}
var bb = []string{"2", "33", "1"}
cc := Intersect(aa, bb)
fmt.Println(cc)
}
func Test_Union(t *testing.T) {
var aa = []string{"43", "33"}
var bb = []string{"2", "33", "1"}
cc := Union(aa, bb)
fmt.Println(cc)
}
func Test_Unique(t *testing.T) {
var str = []string{"1", "2", "2"}
ret, err := Unique(str)
fmt.Println(ret, err)
}
func Test_StringSliceSort(t *testing.T) {
var str = []string{"10", "2", "5"}
ret, err := StringSliceSort(str,"asc")
fmt.Println(ret, err)
ret2, err := StringSliceSort(str,"desc")
fmt.Println(ret2, err)
}

+ 62
- 0
snowflake.go View File

@ -0,0 +1,62 @@
package helper
import (
"sync"
"time"
)
// Snowflake 结构体
type Snowflake struct {
mu sync.Mutex
startTime int64 // 起始时间戳,可以根据实际需求设置
machineID int64 // 机器ID
sequenceNum int64 // 序列号
}
// NewSnowflake 创建一个Snowflake实例
func NewSnowflake(machineID int64) *Snowflake {
return &Snowflake{
startTime: getTimeStamp(),
machineID: machineID,
sequenceNum: 0,
}
}
// Generate 生成一个唯一ID
func (s *Snowflake) Generate() int64 {
s.mu.Lock()
defer s.mu.Unlock()
currentTime := getTimeStamp()
// 如果当前时间小于上一次生成ID的时间,说明时钟回拨,需要等待
if currentTime < s.startTime {
time.Sleep(time.Duration(s.startTime - currentTime))
currentTime = getTimeStamp()
}
// 如果是同一毫秒内生成的ID,需要增加序列号
if currentTime == s.startTime {
s.sequenceNum++
} else {
s.sequenceNum = 0
s.startTime = currentTime
}
// 如果序列号超过了12位的最大值,等待下一毫秒再生成ID
if s.sequenceNum >= 1<<12 {
time.Sleep(time.Millisecond)
s.startTime = getTimeStamp()
s.sequenceNum = 0
}
// 生成ID
id := (currentTime-s.startTime)<<22 | (s.machineID << 12) | s.sequenceNum
return id
}
// 获取当前时间戳(毫秒级)
func getTimeStamp() int64 {
return time.Now().UnixNano() / int64(time.Millisecond)
}

+ 16
- 0
snowflake_test.go View File

@ -0,0 +1,16 @@
package helper
import (
"testing"
)
func Test_snowflake(t *testing.T) {
// 创建一个Snowflake实例
snowflake := NewSnowflake(169379266710)
// 生成10个唯一ID并输出
for i := 0; i < 10; i++ {
id := snowflake.Generate()
t.Log(id)
}
}

+ 57
- 2
string.go View File

@ -31,6 +31,8 @@ func ToString(v interface{}) string {
value = string(v.([]uint8))
// case []byte:
// value = string(v.([]byte))
case time.Time:
value = v.(time.Time).Format("2006-01-02 15:04:05")
case interface{}:
value = v.(string)
case nil:
@ -141,7 +143,7 @@ func ToInt64(inter interface{}) int64 {
return value
}
//生成随机字符串
// 生成随机字符串
func GetRandomString(length int) string {
str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
bytes := []byte(str)
@ -153,7 +155,7 @@ func GetRandomString(length int) string {
return string(result)
}
//生成随机数字
// 生成随机数字
func GetRandomNumber(length int) string {
str := "0123456789"
bytes := []byte(str)
@ -169,6 +171,7 @@ func GetRandomNumber(length int) string {
* 字符串转大驼峰 ios_bbbbbbbb -> IosBbbbbbbbb
*/
func StrFirstToUpper(str string) string {
str = strings.ReplaceAll(str, "`", "")
temp := strings.Split(str, "_")
var upperStr string
for y := 0; y < len(temp); y++ {
@ -203,6 +206,26 @@ func IsInStringArray(arr []string, str string) bool {
return isIn
}
/**
* 字符串在字符切片中对应索引
*/
func InStringArrayIndex(arr []string, str string) int {
// var isIn bool = false
length := len(arr)
if length < 1 {
return -1
}
var index int = -1
for k, item := range arr {
if item == str {
// isIn = true
index = k
break
}
}
return index
}
/*
* 删除多余空格
* 2019/05/05
@ -250,3 +273,35 @@ func UrlJoin(host, url string) string {
return StringJoin(host, url)
}
/**
* 去除字符串的html标签
* @2021/10/20
*/
func TrimHtml(src string) string {
//将HTML标签全转换成小写
re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
src = re.ReplaceAllStringFunc(src, strings.ToLower)
//去除STYLE
re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
src = re.ReplaceAllString(src, "")
//去除SCRIPT
re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
src = re.ReplaceAllString(src, "")
//去除所有尖括号内的HTML代码,并换成换行符
re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
src = re.ReplaceAllString(src, "\n")
//去除连续的换行符
re, _ = regexp.Compile("\\s{2,}")
src = re.ReplaceAllString(src, "\n")
return strings.TrimSpace(src)
}
/**
* 腾讯云图片压缩
* @2021/11/19
* @linsen
*/
func TencentCloudImageCompress(imgUrl, ratio string) string {
return imgUrl + "?imageMogr2/thumbnail/" + ratio + "x/interlace/1"
}

+ 15
- 1
string_test.go View File

@ -1,6 +1,8 @@
package helper
import (
"fmt"
"strings"
"testing"
)
@ -41,8 +43,20 @@ func Test_ToString(t *testing.T) {
t.Log(ret)
}
func Test_StrFirstToUpper(t *testing.T) {
var str string = "departmentID"
ret := StrFirstToUpper(str)
t.Log(ret)
}
func Test_ToInt(t *testing.T) {
var str interface{} = 45
var str string = "sd23455667,123456789aq,qq123456789"
ret := ToInt(str)
t.Log(ret)
}
func Test_IsInStringArray(t *testing.T) {
var s string = "1,19,37,220,351,466,585,655,801,820,933,1046,1168,1263,1375,1532,1709,1827,1965,1977,1988,2003,2011,2017,2025,2035,2041,2050,2056,2065,2070,2077,2082,2091,2123,2146,2150,2156,2162,2291,2323,2367,2572,2670,2816,2898,3022,3126,3178,3206,3325,3716,3738"
arr := strings.Split(s, ",")
t.Log(IsInStringArray(arr, "351"))
}

+ 149
- 0
struct.go View File

@ -0,0 +1,149 @@
package helper
import (
"errors"
"fmt"
"reflect"
)
// 结构体泛型提取关键数据
// desk结构体, input提取数据源, columnKey提取的字段,indexKey提取的下标
func StructColumn(desk, input interface{}, columnKey, indexKey string) (err error) {
deskValue := reflect.ValueOf(desk)
if deskValue.Kind() != reflect.Ptr {
return errors.New("desk must be ptr")
}
rv := reflect.ValueOf(input)
if rv.Kind() != reflect.Slice && rv.Kind() != reflect.Array {
return errors.New("input must be map slice or array")
}
rt := reflect.TypeOf(input)
if rt.Elem().Kind() != reflect.Struct {
return errors.New("input's elem must be struct")
}
if len(indexKey) > 0 {
return structIndexColumn(desk, input, columnKey, indexKey)
}
return structColumn(desk, input, columnKey)
}
func structColumn(desk, input interface{}, columnKey string) (err error) {
if len(columnKey) == 0 {
return errors.New("columnKey cannot not be empty")
}
deskElemType := reflect.TypeOf(desk).Elem()
if deskElemType.Kind() != reflect.Slice {
return errors.New("desk must be slice")
}
rv := reflect.ValueOf(input)
rt := reflect.TypeOf(input)
var columnVal reflect.Value
deskValue := reflect.ValueOf(desk)
direct := reflect.Indirect(deskValue)
for i := 0; i < rv.Len(); i++ {
columnVal, err = findStructValByColumnKey(rv.Index(i), rt.Elem(), columnKey)
if err != nil {
return
}
if deskElemType.Elem().Kind() != columnVal.Kind() {
return errors.New(fmt.Sprintf("your slice must be []%s", columnVal.Kind()))
}
direct.Set(reflect.Append(direct, columnVal))
}
return
}
func findStructValByColumnKey(curVal reflect.Value, elemType reflect.Type, columnKey string) (columnVal reflect.Value, err error) {
columnExist := false
for i := 0; i < elemType.NumField(); i++ {
curField := curVal.Field(i)
if elemType.Field(i).Name == columnKey {
columnExist = true
columnVal = curField
continue
}
}
if !columnExist {
return columnVal, errors.New(fmt.Sprintf("columnKey %s not found in %s's field", columnKey, elemType))
}
return
}
func structIndexColumn(desk, input interface{}, columnKey, indexKey string) (err error) {
deskValue := reflect.ValueOf(desk)
if deskValue.Elem().Kind() != reflect.Map {
return errors.New("desk must be map")
}
deskElem := deskValue.Type().Elem()
if len(columnKey) == 0 && deskElem.Elem().Kind() != reflect.Struct {
return errors.New(fmt.Sprintf("desk's elem expect struct, got %s", deskElem.Elem().Kind()))
}
rv := reflect.ValueOf(input)
rt := reflect.TypeOf(input)
elemType := rt.Elem()
var indexVal, columnVal reflect.Value
direct := reflect.Indirect(deskValue)
mapReflect := reflect.MakeMap(deskElem)
deskKey := deskValue.Type().Elem().Key()
for i := 0; i < rv.Len(); i++ {
curVal := rv.Index(i)
indexVal, columnVal, err = findStructValByIndexKey(curVal, elemType, indexKey, columnKey)
if err != nil {
return
}
if deskKey.Kind() != indexVal.Kind() {
return errors.New(fmt.Sprintf("cant't convert %s to %s, your map'key must be %s", indexVal.Kind(), deskKey.Kind(), indexVal.Kind()))
}
if len(columnKey) == 0 {
mapReflect.SetMapIndex(indexVal, curVal)
direct.Set(mapReflect)
} else {
if deskElem.Elem().Kind() != columnVal.Kind() {
return errors.New(fmt.Sprintf("your map must be map[%s]%s", indexVal.Kind(), columnVal.Kind()))
}
mapReflect.SetMapIndex(indexVal, columnVal)
direct.Set(mapReflect)
}
}
return
}
func findStructValByIndexKey(curVal reflect.Value, elemType reflect.Type, indexKey, columnKey string) (indexVal, columnVal reflect.Value, err error) {
indexExist := false
columnExist := false
for i := 0; i < elemType.NumField(); i++ {
curField := curVal.Field(i)
if elemType.Field(i).Name == indexKey {
switch curField.Kind() {
case reflect.String, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int, reflect.Float64, reflect.Float32:
indexExist = true
indexVal = curField
default:
return indexVal, columnVal, errors.New("indexKey must be int float or string")
}
}
if elemType.Field(i).Name == columnKey {
columnExist = true
columnVal = curField
continue
}
}
if !indexExist {
return indexVal, columnVal, errors.New(fmt.Sprintf("indexKey %s not found in %s's field", indexKey, elemType))
}
if len(columnKey) > 0 && !columnExist {
return indexVal, columnVal, errors.New(fmt.Sprintf("columnKey %s not found in %s's field", columnKey, elemType))
}
return
}

+ 47
- 0
struct_test.go View File

@ -0,0 +1,47 @@
package helper
import (
"testing"
)
type User struct {
ID int
NAME string
}
type UserString struct {
ID string
NAME string
}
func Test_structColumn(t *testing.T) {
user1 := UserString{
ID: "2",
NAME: "zwk",
}
user2 := UserString{
ID: "3",
NAME: "zzz",
}
var list3 []UserString
list3 = append(list3, user1)
list3 = append(list3, user2)
t.Log(list3)
t.Log("---------------------")
var userMap map[string]string
StructColumn(&userMap, list3, "NAME", "ID")
t.Logf("%#v\n", userMap)
t.Log("---------------------")
var userMap1 map[int]UserString
StructColumn(&userMap1, list3, "", "ID")
t.Logf("%#v\n", userMap1)
t.Log("---------------------")
var userSlice []string
StructColumn(&userSlice, list3, "ID", "")
t.Logf("%#v\n", userSlice)
t.Log("---------------------")
}

+ 0
- 0
system.go View File


+ 80
- 0
time.go View File

@ -19,3 +19,83 @@ func FormatDate(str string) string {
}
return time.Unix(date, 0).Format("2006-01-02")
}
// 获取当天开始时间戳
func GetTodayStartTimeStamp() int64 {
var reserveTime time.Time
// loc, _ := time.LoadLocation(time.Location.String())
date := time.Now().Format("2006-01-02")
reserveTime, _ = time.ParseInLocation("2006-01-02", date, time.Local)
return reserveTime.Unix()
}
// 获取当天结束时间戳
func GetTodayEndTimeStamp() int64 {
var reserveTime time.Time
// loc, _ := time.LoadLocation("Asia/Shanghai")
date := time.Now().Format("2006-01-02")
reserveTime, _ = time.ParseInLocation("2006-01-02 15:04:05", date+" 23:59:59", time.Local)
return reserveTime.Unix()
}
// 获取本周开始时间戳
func GetWeekStartTimeStamp() int64 {
var reserveTime time.Time
now := time.Now()
loc, _ := time.LoadLocation("Asia/Shanghai")
offset := int(time.Monday - now.Weekday())
if offset > 0 {
offset = -6
}
weekStartDate := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, offset)
weekMonday := weekStartDate.Format("2006-01-02")
reserveTime, _ = time.ParseInLocation("2006-01-02", weekMonday, loc)
return reserveTime.Unix()
}
// 获取当月开始时间戳
func GetMonthStartTimeStamp() int64 {
var reserveTime time.Time
loc, _ := time.LoadLocation("Asia/Shanghai")
date := time.Now().Format("2006-01")
reserveTime, _ = time.ParseInLocation("2006-01", date, loc)
return reserveTime.Unix()
}
// RFC3339ToCSTLayout convert rfc3339 value to china standard time layout
func RFC3339ToCSTLayout(value string) (string, error) {
var (
cst *time.Location
)
var err error
if cst, err = time.LoadLocation("Asia/Shanghai"); err != nil {
panic(err)
}
ts, err := time.Parse(time.RFC3339, value)
if err != nil {
return "", err
}
return ts.In(cst).Format("2006-01-02 15:04:05"), nil
}
// 具体日期时间转时间戳
func DatetimeToUnix(value string) int64 {
loc, _ := time.LoadLocation("Asia/Shanghai")
reserveTime, _ := time.ParseInLocation("2006-01-02 15:04:05", value, loc)
return reserveTime.Unix()
}

+ 38
- 8
time_test.go View File

@ -3,15 +3,45 @@ package helper
import (
"testing"
"time"
// "time"
)
func Test_FormatDate(t *testing.T) {
str := "1110"
strconv := FormatDate(str)
t.Log(strconv)
// func Test_FormatDate(t *testing.T) {
// str := "1110"
// strconv := FormatDate(str)
// t.Log(strconv)
timing := "2019/1/1 8:28"
ret, err := time.ParseInLocation("2006/1/2 15:04", timing, time.Local)
t.Log(ret.Unix())
t.Log(err)
// timing := "2019/1/1 8:28"
// ret, err := time.ParseInLocation("2006/1/2 15:04", timing, time.Local)
// t.Log(ret.Unix())
// t.Log(err)
// }
// func Test_GetToadyStartTimeStamp(t *testing.T) {
// t.Log(GetMonthStartTimeStamp())
// }
// func Test_RFC3339ToCSTLayout(t *testing.T) {
// cur := "2018-06-08T10:34:56+08:00"
// ret, err := RFC3339ToCSTLayout(cur)
// t.Log(ret)
// t.Log(err)
// }
func Test_GetTodayStartTimeStamp(t *testing.T) {
reserve_date := "2023-05-15"
reserveTime, err := time.ParseInLocation("2006-01-02", reserve_date, time.Local)
if err != nil {
t.Log("err:", err)
}
// 今天0点的时间戳
t.Log(reserveTime.Unix())
}
func Test_DatetimeToUnix(t *testing.T) {
date := "2023-09-01 00:00:00"
t.Log(DatetimeToUnix(date))
}

+ 12
- 0
uuid_test.go View File

@ -0,0 +1,12 @@
package helper
import (
"testing"
)
func Test_GenerateUUID(t *testing.T) {
uuid, err := GenerateUUID()
t.Log(uuid)
t.Log(err)
}

Loading…
Cancel
Save