Commit b0cd1c59 by feidy

切片,泛型MAP,reids test,时间,mq等

parent ff1bb7ab
/*
* @Author: zhoufei
* @Date: 2022-03-14 17:39:16
* @LastEditors: zhoufei
* @LastEditTime: 2022-05-27 09:44:47
* @FilePath: /utils/corn.go
* @Description:
*
* Copyright (c) 2022 by zhoufei, All Rights Reserved.
*/
package utils
import (
......@@ -6,10 +16,12 @@ import (
type CronFunc func()
func NewCron(spec string,fun CronFunc)(cron *c.Cron){
func NewCron(spec string, fun CronFunc) (cron *c.Cron, err error) {
cron = c.New(c.WithSeconds())
cron.AddFunc(spec,fun)
_, err = cron.AddFunc(spec, fun)
if err != nil {
return nil, err
}
cron.Start()
return cron
return cron, nil
}
module gits.shuoren.com/go/utils
go 1.17
go 1.18
require (
github.com/apache/rocketmq-client-go/v2 v2.1.0
github.com/go-playground/assert/v2 v2.0.1
github.com/go-redis/redis/v8 v8.11.5
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/qiniu/qmgo v1.0.6
github.com/robfig/cron/v3 v3.0.1
github.com/stretchr/testify v1.7.0
go.mongodb.org/mongo-driver v1.8.2
go.uber.org/zap v1.21.0
)
require (
github.com/BurntSushi/toml v1.0.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/go-playground/locales v0.13.0 // indirect
github.com/go-playground/universal-translator v0.17.0 // indirect
......@@ -28,6 +33,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/sirupsen/logrus v1.4.1 // indirect
github.com/tidwall/gjson v1.14.1 // indirect
github.com/tidwall/match v1.1.1 // indirect
......@@ -40,8 +46,9 @@ require (
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect
golang.org/x/text v0.3.5 // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
golang.org/x/text v0.3.6 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
stathat.com/c/consistent v1.0.0 // indirect
)
/*
* @Author: zhoufei
* @Date: 2022-05-19 15:41:06
* @LastEditors: zhoufei
* @LastEditTime: 2022-06-07 14:18:16
* @FilePath: /utils/map_g.go
* @Description: 泛型map
*
* Copyright (c) 2022 by zhoufei, All Rights Reserved.
*/
package utils
import (
"sync"
"time"
)
const (
// NeverDie means value.alive() returns true forever.
NeverDieG = 0
)
type valueG[T any] struct {
data T
ttl int64
ctime time.Time
}
func newValueG[T any](data T, ttl int64) *valueG[T] {
return &valueG[T]{data: data, ttl: ttl, ctime: time.Now()}
}
func (v *valueG[T]) alive() bool {
return v.ttl == NeverDieG || time.Now().Before(v.ctime.Add(time.Duration(v.ttl)*time.Second))
}
type Map[K comparable, T any] struct {
data map[K]*valueG[T]
lock *sync.RWMutex
}
func NewMap[K comparable, T any]() *Map[K, T] {
return &Map[K, T]{data: make(map[K]*valueG[T]), lock: &sync.RWMutex{}}
}
func (m *Map[K, T]) Set(key K, data T, ttl int64) {
m.lock.Lock()
defer m.lock.Unlock()
m.data[key] = newValueG(data, ttl)
}
func (m *Map[K, T]) Get(key K) (T, bool) {
var d T
m.lock.Lock()
defer m.lock.Unlock()
if value, ok := m.data[key]; ok {
return value.data, true
}
return d, false
}
func (m *Map[K, T]) Len() int {
m.lock.Lock()
defer m.lock.Unlock()
return len(m.data)
}
func (m *Map[K, T]) Keys() []K {
m.lock.Lock()
defer m.lock.Unlock()
keys := make([]K, 0, len(m.data))
for k := range m.data {
keys = append(keys, k)
}
return keys
}
func (m *Map[K, T]) Values() []T {
m.lock.Lock()
defer m.lock.Unlock()
values := make([]T, 0, len(m.data))
for _, v := range m.data {
values = append(values, v.data)
}
return values
}
func (m *Map[K, T]) CloneTo(another *Map[K, T]) {
for k := range m.data {
another.data[k] = m.data[k]
}
}
func (m *Map[K, T]) Del(k K) {
m.lock.Lock()
defer m.lock.Unlock()
delete(m.data, k)
}
func (m *Map[K, T]) Gc() {
m.lock.Lock()
defer m.lock.Unlock()
for k, v := range m.data {
if !v.alive() {
delete(m.data, k)
}
}
}
func (m *Map[K, T]) AutoGc(duration time.Duration) {
go func() {
ticker := time.NewTicker(duration)
for {
<-ticker.C
m.Gc()
}
}()
}
/*
* @Author: zhoufei
* @Date: 2022-05-19 16:05:49
* @LastEditors: zhoufei
* @LastEditTime: 2022-05-26 10:29:58
* @FilePath: /utils/map_g_test.go
* @Description:
*
* Copyright (c) 2022 by zhoufei, All Rights Reserved.
*/
package utils
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestMapG(t *testing.T) {
m := NewMap[string, string]()
m.Set("a", "b", 0)
b, _ := m.Get("a")
assert.Equal(t, b, "b")
}
func TestMapClone(t *testing.T) {
a := NewMap[string, string]()
a.Set("a", "b", 0)
bb := NewMap[string, string]()
a.CloneTo(bb)
bb.Set("a", "c", 0)
a.Set("a", "d", 0)
aa, ok := bb.Get("a")
assert.Equal(t, true, ok)
assert.Equal(t, "c", aa)
aaa, ok := a.Get("a")
assert.Equal(t, true, ok)
assert.Equal(t, "d", aaa)
}
/*
* @Author: zhoufei
* @Date: 2022-03-04 14:35:55
* @LastEditors: zhoufei
* @LastEditTime: 2022-05-27 09:54:50
* @FilePath: /utils/mongodb_test.go
* @Description:
*
* Copyright (c) 2022 by zhoufei, All Rights Reserved.
*/
package utils
import (
"context"
"testing"
"github.com/go-playground/assert/v2"
"go.mongodb.org/mongo-driver/bson"
"testing"
)
func TestMongo_InitCli(t *testing.T) {
m,err := NewMongo("192.168.31.129:27017/snc","snc","shuoren@2019snc",
WithDB("snc"),WithCollection("alarm"))
defer m.Close()
if err != nil{
m, err := NewMongo("192.168.31.129:27017/snc", "snc", "shuoren@2019snc",
WithDB("snc"), WithCollection("alarm"))
if err != nil {
t.Fatal(err)
}
c,err := m.Cli.Find(context.Background(),bson.M{}).Count()
if err != nil{
defer m.Close()
c, err := m.Cli.Find(context.Background(), bson.M{}).Count()
if err != nil {
t.Fatal(err)
}
count := int64(37415)
assert.Equal(t,c,count)
count := int64(38999)
assert.Equal(t, c, count)
}
func TestMongo_InitClient(t *testing.T){
m,err := NewMongo("192.168.31.129:27017/snc","snc","shuoren@2019snc")
defer m.Close()
if err != nil{
func TestMongo_InitClient(t *testing.T) {
m, err := NewMongo("192.168.31.129:27017/snc", "snc", "shuoren@2019snc")
if err != nil {
t.Fatal(err)
}
c,err := m.Client.Database("snc").Collection("alarm").Find(context.Background(),bson.M{}).Count()
if err != nil{
defer m.Close()
c, err := m.Client.Database("snc").Collection("alarm").Find(context.Background(), bson.M{}).Count()
if err != nil {
t.Fatal(err)
}
count := int64(37415)
assert.Equal(t,c,count)
}
\ No newline at end of file
count := int64(38999)
assert.Equal(t, c, count)
}
......@@ -2,7 +2,7 @@
* @Author: zhoufei
* @Date: 2022-04-22 14:58:25
* @LastEditors: zhoufei
* @LastEditTime: 2022-05-06 14:36:10
* @LastEditTime: 2022-05-31 16:53:30
* @FilePath: /utils/queue/rocketmq.go
* @Description:rocketmq 工具类
* 注意:rocketmq-client-go/v2 在1.18下会闪退,需要手动更改json-iterator/go 到 v1.1.12 (2022-4-25)
......@@ -19,6 +19,7 @@ import (
"github.com/apache/rocketmq-client-go/v2/consumer"
"github.com/apache/rocketmq-client-go/v2/primitive"
"github.com/apache/rocketmq-client-go/v2/producer"
"github.com/apache/rocketmq-client-go/v2/rlog"
)
type RocketMq struct {
......@@ -44,6 +45,10 @@ func WithRocketAcl(access string, secret string) RocketOption {
}
}
func init() {
rlog.SetLogLevel("error")
}
/**
* @description: 发送消息
* @param {string} topic
......@@ -143,7 +148,7 @@ func (r *RocketMq) RegisterConsumer(topic string, recevieFunc func(qMsg *QueueMs
err = r.consumer.Start()
if err != nil {
r.consumer.Unsubscribe(topic)
err = r.consumer.Unsubscribe(topic)
return err
}
return nil
......@@ -190,6 +195,7 @@ func NewRocketMqProducer(endPoints []string, groupName string, retry int, option
}
client, err := rocketmq.NewProducer(opts...)
if err != nil {
return nil, err
}
......
/*
* @Author: zhoufei
* @Date: 2022-05-16 11:39:43
* @LastEditors: zhoufei
* @LastEditTime: 2022-05-16 12:03:55
* @FilePath: /utils/redis.go
* @Description: redis 相关操作
*
* Copyright (c) 2022 by zhoufei, All Rights Reserved.
*/
package utils
import "github.com/go-redis/redis/v8"
type Redis struct {
Client *redis.Client
}
func NewRedis(addr string, password string, db int) (r *Redis, err error) {
return &Redis{
Client: redis.NewClient(&redis.Options{
Addr: addr,
Password: password,
DB: db,
}),
}, nil
}
/*
* @Author: zhoufei
* @Date: 2022-06-08 09:54:03
* @LastEditors: zhoufei
* @LastEditTime: 2022-06-08 14:22:38
* @FilePath: /utils/redis_test.go
* @Description:
*
* Copyright (c) 2022 by zhoufei, All Rights Reserved.
*/
package utils
import (
"context"
"fmt"
"testing"
"github.com/go-redis/redis/v8"
)
func TestRedisLua(t *testing.T) {
var realData1 = redis.NewScript(`
local function aa()
return "5"
end
local r = aa()
-- 获取所有key
local keys = cjson.decode(KEYS[1])
-- 获取所有的数据
local values = cjson.decode(ARGV[1])
for k, v in ipairs(keys) do
-- 获取redis实时数据
local rd = redis.call("get", v)
if rd then
local rdt = cjson.decode(rd)
if rdt then
if (values[v]["time"] > rdt["time"]) then
if (values[v]["expire"] > 0) then
redis.call("SET", v, cjson.encode(values[v]),"EX",values[v]["expire"])
else
redis.call("SET", v, cjson.encode(values[v]))
end
end
end
else
if (values[v]["expire"] > 0) then
local a = redis.call("SET", v, cjson.encode(values[v]),"EX",values[v]["expire"])
else
redis.call("SET", v, cjson.encode(values[v]))
end
end
end
return r
`)
rdb, err := NewRedis("192.168.31.129:6379", "123456", 0)
if err != nil {
t.Fatal(err)
}
if err := rdb.Client.Ping(context.Background()).Err(); err != nil {
t.Fatal(err)
}
defer rdb.Client.Close()
testKeys := `["aaaa","bbb"]`
testValues := `{"aaaa":{"protoCode":"aaaa","param":"tn","time":223456789,"value":12.5,"expire":0},"bbb":{"protoCode":"bbb","param":"tn","time":243456789,"value":12.5,"expire":10}}`
r, err := realData1.Run(context.Background(), rdb.Client, []string{testKeys}, testValues).Result()
fmt.Println("11111")
// rmd, err := realData.Run(context.Background(), rdb.Client, []string{}).Result()
if err != nil {
t.Fatal(err)
}
fmt.Println(r)
}
/*
* @Author: zhoufei
* @Date: 2022-05-25 13:54:05
* @LastEditors: zhoufei
* @LastEditTime: 2022-06-07 11:57:37
* @FilePath: /sdc/Users/software/Documents/go/utils/slice.go
* @Description:
*
* Copyright (c) 2022 by zhoufei, All Rights Reserved.
*/
package utils
import "reflect"
func SliceIsContain[T any](array []T, value T) (index int, ok bool) {
for i, v := range array {
if reflect.DeepEqual(v, value) {
return i, true
}
}
return -1, false
}
func SliceDel[T comparable](array []T, values ...T) []T {
if len(values) == 0 {
return array
}
m := make(map[T]struct{})
for _, v := range values {
m[v] = struct{}{}
}
res := make([]T, 0, len(array))
for _, v := range array {
if _, ok := m[v]; !ok {
res = append(res, v)
}
}
return res
}
/*
* @Author: zhoufei
* @Date: 2022-05-25 14:41:48
* @LastEditors: zhoufei
* @LastEditTime: 2022-06-07 14:19:50
* @FilePath: /utils/slice_test.go
* @Description:
*
* Copyright (c) 2022 by zhoufei, All Rights Reserved.
*/
package utils
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSliceIsContain(t *testing.T) {
_, isContain := SliceIsContain([]string{"a", "b", "c"}, "a")
assert.Equal(t, true, isContain)
}
func TestSliceDel(t *testing.T) {
assert.Equal(t, []string{"a", "b"}, SliceDel([]string{"a", "b", "c"}, "c"))
assert.Equal(t, []string{"a", "b", "c"}, SliceDel([]string{"a", "b", "c"}))
}
/*
* @Author: zhoufei
* @Date: 2022-06-01 15:20:40
* @LastEditors: zhoufei
* @LastEditTime: 2022-06-01 15:27:22
* @FilePath: /utils/some_test.go
* @Description:
*
* Copyright (c) 2022 by zhoufei, All Rights Reserved.
*/
package utils
import (
"fmt"
"testing"
jsoniter "github.com/json-iterator/go"
"github.com/stretchr/testify/assert"
)
func TestSome(t *testing.T) {
v := 20
assert.Equal(t, ttt(v), int64(200000))
}
func ttt(a interface{}) int64 {
return int64(a.(int) * 10000)
}
var jsonIterator = jsoniter.ConfigCompatibleWithStandardLibrary
func TestJson(t *testing.T) {
json := `{"a":20,"b":20.6,"c":"123","d":111.2,"e":9999}`
var st map[string]interface{}
err := jsonIterator.Unmarshal([]byte(json), &st)
if err != nil {
t.Fatal(err)
}
for _, v := range st {
if vv, ok := v.(float64); ok {
fmt.Println(int64(vv * 10000))
}
}
fmt.Println(st)
}
/*
* @Author: zhoufei
* @Date: 2022-03-15 18:26:05
* @LastEditors: zhoufei
* @LastEditTime: 2022-06-02 09:26:34
* @FilePath: /utils/strconv.go
* @Description:
*
* Copyright (c) 2022 by zhoufei, All Rights Reserved.
*/
package utils
import (
"fmt"
"math"
"strconv"
)
......@@ -34,3 +45,8 @@ func FloatRound(f float64, n int) float64 {
res, _ := strconv.ParseFloat(fmt.Sprintf(format, f), 64)
return res
}
// 小数四舍五入到整型
func FloatRoundUp(f float64) int {
return int(math.Ceil(f - 0.5))
}
/*
* @Author: zhoufei
* @Date: 2022-06-01 14:18:44
* @LastEditors: zhoufei
* @LastEditTime: 2022-06-01 15:20:48
* @FilePath: /utils/time_test.go
* @Description:
*
* Copyright (c) 2022 by zhoufei, All Rights Reserved.
*/
package utils
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestTime(t *testing.T) {
m := ToMinute(MillisecondToTime(1654014780000))
fmt.Println(m)
nd := time.Date(m.Year(), m.Month(), m.Day(), m.Hour(), m.Minute()/10*10, 0, 0, m.Location()).Add(time.Hour * -1)
fmt.Println(nd)
ddt := TimeToTimestamp(nd)
assert.Equal(t, ddt, int64(1654011000000))
}
......@@ -64,6 +64,11 @@ func ThisYear(t time.Time) time.Time {
return time.Date(t.Year(), 1, 1, 0, 0, 0, 0, t.Location())
}
func ThisHour(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, t.Hour(), 0, 0, 0, t.Location())
}
// TimestampToTime second timestamp to Time
func TimestampToTime(u int64) time.Time {
return time.Unix(u, 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment