Compare commits

...

11 Commits

Author SHA1 Message Date
ayflying
f349dca0f7 所有包同意改为pkg 2025-03-25 15:00:54 +08:00
ayflying
58f00b4f8e 跟新mod 2025-03-25 14:24:56 +08:00
ayflying
d9ab1be2e7 更新pb目录 2025-03-25 14:14:48 +08:00
ayflying
4b77cd140d 初始化驱动 2025-03-25 14:06:03 +08:00
ayflying
8d640be472 增加websocket库 2025-03-24 17:39:09 +08:00
ayflying
cc08e830d3 分离websocket 2025-03-21 16:33:44 +08:00
ayflying
696f1bcbdb 导表支持忽略注释行 2025-03-20 16:22:28 +08:00
ayflying
5c45ddb80b 修改引用头部,不是用ctx 2025-03-19 17:41:23 +08:00
ayflying
14de836089 调整缓存key,增加kv持久化方法 2025-03-18 16:16:44 +08:00
ayflying
1c4f804738 修改持久化的顺序 2025-03-17 11:21:37 +08:00
ayflying
5fbe4d5dcf 更新库pkg 2025-03-14 14:26:07 +08:00
44 changed files with 1055 additions and 528 deletions

View File

@@ -2,7 +2,7 @@
// versions:
// protoc-gen-go v1.28.1
// protoc v3.20.0
// source: pgk/v1/pgk.proto
// source: pkg/v1/pkg.proto
package v1
@@ -61,11 +61,11 @@ func (x NoticeType) String() string {
}
func (NoticeType) Descriptor() protoreflect.EnumDescriptor {
return file_pgk_v1_pgk_proto_enumTypes[0].Descriptor()
return file_pkg_v1_pkg_proto_enumTypes[0].Descriptor()
}
func (NoticeType) Type() protoreflect.EnumType {
return &file_pgk_v1_pgk_proto_enumTypes[0]
return &file_pkg_v1_pkg_proto_enumTypes[0]
}
func (x NoticeType) Number() protoreflect.EnumNumber {
@@ -74,7 +74,7 @@ func (x NoticeType) Number() protoreflect.EnumNumber {
// Deprecated: Use NoticeType.Descriptor instead.
func (NoticeType) EnumDescriptor() ([]byte, []int) {
return file_pgk_v1_pgk_proto_rawDescGZIP(), []int{0}
return file_pkg_v1_pkg_proto_rawDescGZIP(), []int{0}
}
// 排行榜数据
@@ -92,7 +92,7 @@ type RankData struct {
func (x *RankData) Reset() {
*x = RankData{}
if protoimpl.UnsafeEnabled {
mi := &file_pgk_v1_pgk_proto_msgTypes[0]
mi := &file_pkg_v1_pkg_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -105,7 +105,7 @@ func (x *RankData) String() string {
func (*RankData) ProtoMessage() {}
func (x *RankData) ProtoReflect() protoreflect.Message {
mi := &file_pgk_v1_pgk_proto_msgTypes[0]
mi := &file_pkg_v1_pkg_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -118,7 +118,7 @@ func (x *RankData) ProtoReflect() protoreflect.Message {
// Deprecated: Use RankData.ProtoReflect.Descriptor instead.
func (*RankData) Descriptor() ([]byte, []int) {
return file_pgk_v1_pgk_proto_rawDescGZIP(), []int{0}
return file_pkg_v1_pkg_proto_rawDescGZIP(), []int{0}
}
func (x *RankData) GetId() int64 {
@@ -149,10 +149,10 @@ func (x *RankData) GetUpdateTs() int64 {
return 0
}
var File_pgk_v1_pgk_proto protoreflect.FileDescriptor
var File_pkg_v1_pkg_proto protoreflect.FileDescriptor
var file_pgk_v1_pgk_proto_rawDesc = []byte{
0x0a, 0x10, 0x70, 0x67, 0x6b, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x67, 0x6b, 0x2e, 0x70, 0x72, 0x6f,
var file_pkg_v1_pkg_proto_rawDesc = []byte{
0x0a, 0x10, 0x70, 0x6b, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x6b, 0x67, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x22, 0x61, 0x0a, 0x08, 0x52,
0x61, 0x6e, 0x6b, 0x44, 0x61, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65,
@@ -166,29 +166,29 @@ var file_pgk_v1_pgk_proto_rawDesc = []byte{
0x02, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x4d, 0x53, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x56, 0x4f,
0x49, 0x43, 0x45, 0x10, 0x04, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x79, 0x66, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x2f, 0x75, 0x74, 0x69,
0x6c, 0x69, 0x74, 0x79, 0x5f, 0x67, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x67, 0x6b, 0x2f,
0x6c, 0x69, 0x74, 0x79, 0x5f, 0x67, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6b, 0x67, 0x2f,
0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_pgk_v1_pgk_proto_rawDescOnce sync.Once
file_pgk_v1_pgk_proto_rawDescData = file_pgk_v1_pgk_proto_rawDesc
file_pkg_v1_pkg_proto_rawDescOnce sync.Once
file_pkg_v1_pkg_proto_rawDescData = file_pkg_v1_pkg_proto_rawDesc
)
func file_pgk_v1_pgk_proto_rawDescGZIP() []byte {
file_pgk_v1_pgk_proto_rawDescOnce.Do(func() {
file_pgk_v1_pgk_proto_rawDescData = protoimpl.X.CompressGZIP(file_pgk_v1_pgk_proto_rawDescData)
func file_pkg_v1_pkg_proto_rawDescGZIP() []byte {
file_pkg_v1_pkg_proto_rawDescOnce.Do(func() {
file_pkg_v1_pkg_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_v1_pkg_proto_rawDescData)
})
return file_pgk_v1_pgk_proto_rawDescData
return file_pkg_v1_pkg_proto_rawDescData
}
var file_pgk_v1_pgk_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_pgk_v1_pgk_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_pgk_v1_pgk_proto_goTypes = []interface{}{
var file_pkg_v1_pkg_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_pkg_v1_pkg_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_pkg_v1_pkg_proto_goTypes = []interface{}{
(NoticeType)(0), // 0: package.NoticeType
(*RankData)(nil), // 1: package.RankData
}
var file_pgk_v1_pgk_proto_depIdxs = []int32{
var file_pkg_v1_pkg_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
@@ -196,13 +196,13 @@ var file_pgk_v1_pgk_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for field type_name
}
func init() { file_pgk_v1_pgk_proto_init() }
func file_pgk_v1_pgk_proto_init() {
if File_pgk_v1_pgk_proto != nil {
func init() { file_pkg_v1_pkg_proto_init() }
func file_pkg_v1_pkg_proto_init() {
if File_pkg_v1_pkg_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_pgk_v1_pgk_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
file_pkg_v1_pkg_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RankData); i {
case 0:
return &v.state
@@ -219,19 +219,19 @@ func file_pgk_v1_pgk_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_pgk_v1_pgk_proto_rawDesc,
RawDescriptor: file_pkg_v1_pkg_proto_rawDesc,
NumEnums: 1,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_pgk_v1_pgk_proto_goTypes,
DependencyIndexes: file_pgk_v1_pgk_proto_depIdxs,
EnumInfos: file_pgk_v1_pgk_proto_enumTypes,
MessageInfos: file_pgk_v1_pgk_proto_msgTypes,
GoTypes: file_pkg_v1_pkg_proto_goTypes,
DependencyIndexes: file_pkg_v1_pkg_proto_depIdxs,
EnumInfos: file_pkg_v1_pkg_proto_enumTypes,
MessageInfos: file_pkg_v1_pkg_proto_msgTypes,
}.Build()
File_pgk_v1_pgk_proto = out.File
file_pgk_v1_pgk_proto_rawDesc = nil
file_pgk_v1_pgk_proto_goTypes = nil
file_pgk_v1_pgk_proto_depIdxs = nil
File_pkg_v1_pkg_proto = out.File
file_pkg_v1_pkg_proto_rawDesc = nil
file_pkg_v1_pkg_proto_goTypes = nil
file_pkg_v1_pkg_proto_depIdxs = nil
}

View File

@@ -1,7 +1,8 @@
package aycache
import (
"github.com/ayflying/utility_go/package/aycache/drive"
"github.com/ayflying/utility_go/pkg/aycache/drive"
drive2 "github.com/ayflying/utility_go/pkg/aycache/drive"
"github.com/gogf/gf/v2/os/gcache"
)
@@ -13,7 +14,7 @@ type Mod struct {
// return pgk.Cache
//}
// Deprecated: Use pgk.Cache()
// Deprecated:弃用,改用 pgk.Cache()
func New(_name ...string) gcache.Adapter {
var cacheAdapterObj gcache.Adapter
@@ -23,11 +24,11 @@ func New(_name ...string) gcache.Adapter {
}
switch name {
case "cache":
cacheAdapterObj = NewAdapterMemory()
cacheAdapterObj = drive2.NewAdapterMemory()
case "redis":
cacheAdapterObj = NewAdapterRedis()
cacheAdapterObj = drive2.NewAdapterRedis()
case "file":
cacheAdapterObj = NewAdapterFile("runtime/cache")
cacheAdapterObj = drive2.NewAdapterFile("runtime/cache")
case "es":
cacheAdapterObj = drive.NewAdapterElasticsearch([]string{"http://127.0.0.1:9200"})
}

View File

@@ -2,7 +2,6 @@ package act{id}
import (
service2 "github.com/ayflying/utility_go/service"
"github.com/gogf/gf/v2/os/gctx"
)
type sAct{id} struct {
@@ -14,7 +13,7 @@ func New() *sAct{id} {
var (
ActId = {id}
ctx = gctx.New()
Name = ""
)
type Data struct {

View File

@@ -9,7 +9,7 @@ type s{name} struct {
}
var (
ctx = gctx.New()
)
func New() *s{name} {

View File

@@ -62,9 +62,9 @@ func MiddlewareAdmin(r *ghttp.Request) {
ip := r.GetClientIp()
r.SetCtxVar("ip", ip)
get := r.Cookie.Get("uid")
getUid := r.Cookie.Get("uid")
if get == nil {
if getUid == nil {
//调试模式允许不验证用户名
debug, _ := g.Cfg().GetWithEnv(nil, "debug")
if !debug.Bool() {
@@ -82,7 +82,13 @@ func MiddlewareAdmin(r *ghttp.Request) {
}
uid := get.Int()
uid := getUid.Int()
//获取所有请求的信息
get := r.GetRequestMapStrStr()
if _, ok := get["uid"]; ok {
r.SetCtxVar("uid", get["uid"])
}
r.Middleware.Next()

View File

@@ -0,0 +1,83 @@
package elasticsearch
import (
"github.com/elastic/go-elasticsearch/v8"
)
var (
es *elasticsearch.TypedClient
)
type elastic struct {
client *elasticsearch.TypedClient
}
//func (d *Driver) Insert(ctx context.Context, table string, data interface{}, batch ...int) (res sql.Result, err error) {
//
// return
//}
//
//// createIndex 创建索引
//func (d *Driver) CreateIndex(name string) {
//
// resp, err := d.client.Indices.
// Create(name).
// Do(context.Background())
// if err != nil {
// fmt.Printf("create index failed, err:%v\n", err)
// return
// }
// fmt.Printf("index:%#v\n", resp.Index)
//}
//
//// indexDocument 索引文档
//func (d *Driver) IndexDocument(name string, key string, data interface{}) {
//
// // 添加文档
// resp, err := d.client.Index(name).
// Id(key).
// Document(data).
// Do(context.Background())
// if err != nil {
// fmt.Printf("indexing document failed, err:%v\n", err)
// return
// }
// fmt.Printf("result:%#v\n", resp.Result)
//}
//
//// getDocument 获取文档
//func (d *Driver) GetDocument(name string, id string) (res json.RawMessage) {
// resp, err := d.client.Get(name, id).
// Do(context.Background())
// if err != nil {
// fmt.Printf("get document by id failed, err:%v\n", err)
// return
// }
// fmt.Printf("fileds:%d\n", resp.Source_)
// res = resp.Source_
// return
//}
//
//// updateDocument 更新文档
//func (d *Driver) UpdateDocument(name string, key string, data interface{}) {
//
// resp, err := d.client.Update(name, key).
// Doc(data). // 使用结构体变量更新
// Do(context.Background())
// if err != nil {
// fmt.Printf("update document failed, err:%v\n", err)
// return
// }
// fmt.Printf("result:%v\n", resp.Result)
//}
//
//// deleteDocument 删除 document
//func (d *Driver) DeleteDocument(name string, key string) {
// resp, err := d.client.Delete(name, key).
// Do(context.Background())
// if err != nil {
// fmt.Printf("delete document failed, err:%v\n", err)
// return
// }
// fmt.Printf("result:%v\n", resp.Result)
//}

View File

@@ -0,0 +1,39 @@
package elasticsearch
import (
"database/sql"
"github.com/elastic/go-elasticsearch/v8"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
)
func (d *Driver) Open(config *gdb.ConfigNode) (db *sql.DB, err error) {
var (
source string
underlyingDriverName = "elasticsearch"
)
source = config.Host
cfg := elasticsearch.Config{
Addresses: []string{
config.Host,
},
}
es, err = elasticsearch.NewTypedClient(cfg)
//if err != nil {
// fmt.Printf("elasticsearch.NewTypedClient failed, err:%v\n", err)
// return
//}
if db, err = sql.Open(underlyingDriverName, source); err != nil {
err = gerror.WrapCodef(
gcode.CodeDbOperationError, err,
`sql.Open failed for driver "%s" by source "%s"`, underlyingDriverName, source,
)
return nil, err
}
return
}

View File

@@ -0,0 +1,47 @@
package elasticsearch
import (
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// Driver is the driver for mysql database.
type Driver struct {
*gdb.Core
}
const (
quoteChar = "`"
)
func init() {
var (
err error
driverObj = New()
driverNames = g.SliceStr{"es", "elasticsearch"}
)
for _, driverName := range driverNames {
if err = gdb.Register(driverName, driverObj); err != nil {
panic(err)
}
}
}
// New create and returns a driver that implements gdb.Driver, which supports operations for MySQL.
func New() gdb.Driver {
return &Driver{}
}
// New creates and returns a database object for mysql.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *Driver) New(core *gdb.Core, node *gdb.ConfigNode) (res gdb.DB, err error) {
res = &Driver{
Core: core,
}
return
}
// GetChars returns the security char for this type of database.
func (d *Driver) GetChars() (charLeft string, charRight string) {
return quoteChar, quoteChar
}

53
drivers/db/found/found.go Normal file
View File

@@ -0,0 +1,53 @@
package found
import (
"database/sql"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// Driver is the driver for mysql database.
type Driver struct {
*gdb.Core
}
func (d *Driver) Open(config *gdb.ConfigNode) (*sql.DB, error) {
//TODO implement me
panic("implement me")
}
const (
quoteChar = "`"
)
func init() {
var (
err error
driverObj = New()
driverNames = g.SliceStr{"es", "found"}
)
for _, driverName := range driverNames {
if err = gdb.Register(driverName, driverObj); err != nil {
panic(err)
}
}
}
// New create and returns a driver that implements gdb.Driver, which supports operations for MySQL.
func New() gdb.Driver {
return &Driver{}
}
// New creates and returns a database object for mysql.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *Driver) New(core *gdb.Core, node *gdb.ConfigNode) (res gdb.DB, err error) {
res = &Driver{
Core: core,
}
return
}
// GetChars returns the security char for this type of database.
func (d *Driver) GetChars() (charLeft string, charRight string) {
return quoteChar, quoteChar
}

18
go.mod
View File

@@ -10,14 +10,17 @@ require (
github.com/go-pay/gopay v1.5.109
github.com/go-pay/util v0.0.4
github.com/goccy/go-json v0.10.4
github.com/gogf/gf/contrib/config/apollo/v2 v2.8.3
github.com/gogf/gf/v2 v2.8.3
github.com/gogf/gf/contrib/config/apollo/v2 v2.9.0
github.com/gogf/gf/v2 v2.9.0
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20241220152942-06eb5c6e8230
github.com/minio/minio-go/v7 v7.0.85
github.com/xuri/excelize/v2 v2.9.0
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
google.golang.org/api v0.44.0
google.golang.org/protobuf v1.26.0
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
)
require (
@@ -39,9 +42,7 @@ require (
github.com/go-pay/xtime v0.0.2 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/gax-go/v2 v2.0.5 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/grokify/html-strip-tags-go v0.1.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/klauspost/compress v1.17.11 // indirect
@@ -68,10 +69,10 @@ require (
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
go.opencensus.io v0.23.0 // indirect
go.opentelemetry.io/otel v1.28.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
go.opentelemetry.io/otel v1.32.0 // indirect
go.opentelemetry.io/otel/metric v1.32.0 // indirect
go.opentelemetry.io/otel/sdk v1.32.0 // indirect
go.opentelemetry.io/otel/trace v1.32.0 // indirect
golang.org/x/crypto v0.33.0 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/sys v0.30.0 // indirect
@@ -80,7 +81,6 @@ require (
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
google.golang.org/grpc v1.38.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

35
go.sum
View File

@@ -122,10 +122,10 @@ github.com/go-pay/xtime v0.0.2/go.mod h1:W1yRbJaSt4CSBcdAtLBQ8xajiN/Pl5hquGczUcU
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogf/gf/contrib/config/apollo/v2 v2.8.3 h1:KU51l3uaU7Mxq+FSoLjROyDERUGKCMo4qExxPEgA7KQ=
github.com/gogf/gf/contrib/config/apollo/v2 v2.8.3/go.mod h1:Uo6f/Pr6zVHSbdP2Lj9iToEMuh/TzU/bE2E5SJlquEk=
github.com/gogf/gf/v2 v2.8.3 h1:h9Px3lqJnnH6It0AqHRz4/1hx0JmvaSf1IvUir5x1rA=
github.com/gogf/gf/v2 v2.8.3/go.mod h1:n++xPYGUUMadw6IygLEgGZqc6y6DRLrJKg5kqCrPLWY=
github.com/gogf/gf/contrib/config/apollo/v2 v2.9.0 h1:BewnDc3gq2iqYzPH56FtOelmT9F9WcAm6nnlOVgw3J8=
github.com/gogf/gf/contrib/config/apollo/v2 v2.9.0/go.mod h1:uNjaJcnMvMl7bkcoL0amxwcrOM+Q5XGADKKwKTY+8MY=
github.com/gogf/gf/v2 v2.9.0 h1:semN5Q5qGjDQEv4620VzxcJzJlSD07gmyJ9Sy9zfbHk=
github.com/gogf/gf/v2 v2.9.0/go.mod h1:sWGQw+pLILtuHmbOxoe0D+0DdaXxbleT57axOLH2vKI=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -300,8 +300,8 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
@@ -329,8 +329,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tevid/gohamcrest v1.1.1 h1:ou+xSqlIw1xfGTg1uq1nif/htZ2S3EzRqLm2BP+tYU0=
@@ -357,14 +357,14 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
@@ -699,8 +699,9 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
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/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
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=

View File

@@ -4,8 +4,8 @@ import (
"fmt"
"github.com/ayflying/utility_go/internal/model/do"
"github.com/ayflying/utility_go/internal/model/entity"
"github.com/ayflying/utility_go/package/aycache"
"github.com/ayflying/utility_go/pgk"
"github.com/ayflying/utility_go/pkg"
service2 "github.com/ayflying/utility_go/service"
"github.com/ayflying/utility_go/tools"
"github.com/gogf/gf/v2/container/gset"
@@ -70,8 +70,8 @@ func (s *sGameAct) Info(uid int64, actId int) (data *g.Var, err error) {
// 将查询到的活动信息保存到Redis缓存中
_, err = g.Redis().Set(ctx, keyCache, data)
var ActUidUpdateTimeCacheKey = fmt.Sprintf("act:update:%d", uid)
aycache.New("redis").Set(ctx, ActUidUpdateTimeCacheKey, uid, time.Hour*24*3)
var CacheKey = fmt.Sprintf("act:update:%d", uid)
pkg.Cache("redis").Set(ctx, CacheKey, uid, time.Hour*24*1)
return
}
@@ -137,29 +137,22 @@ func (s *sGameAct) Save(actId int) (err error) {
}
cacheGet, _ := g.Redis().Get(ctx, cacheKey)
//最后删除key
delKey = append(delKey, cacheKey)
if uid == 0 {
//跳过为空的用户缓存
continue
}
if cacheGet.IsEmpty() {
//空数据也不保存
//空数据也不保存
continue
}
var ActUidUpdateTimeCacheKey = fmt.Sprintf("act:update:%d", uid)
//如果有活跃,跳过持久化
if getBool, _ := aycache.New("redis").Contains(ctx, ActUidUpdateTimeCacheKey); getBool {
if getBool, _ := pkg.Cache("redis").Contains(ctx,
fmt.Sprintf("act:update:%d", uid)); getBool {
continue
}
////如果1天没有活跃跳过
//user, _ := service.MemberUser().Info(uid)
//if user.UpdatedAt.Seconds < gtime.Now().Add(consts.ActSaveTime).Unix() {
// continue
//}
//获取数据库数据
var data *entity.GameAct
// 从数据库中查询活动信息
@@ -184,7 +177,8 @@ func (s *sGameAct) Save(actId int) (err error) {
data.Action = actionData
add = append(add, data)
}
//最后删除key
delKey = append(delKey, cacheKey)
}
//批量写入数据库

View File

@@ -0,0 +1,125 @@
package gameKv
import (
"github.com/ayflying/utility_go/service"
"github.com/ayflying/utility_go/tools"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"strconv"
"strings"
"sync"
)
var (
ctx = gctx.New()
Name = "game_kv"
)
type sGameKv struct {
Lock sync.Mutex
}
func New() *sGameKv {
return &sGameKv{}
}
func init() {
service.RegisterGameKv(New())
//支付钩子
//task.Task.Trigger(tasks.TaskType_PAY, service.GameKv().HookPay)
//task.Task.Trigger(tasks.TaskType_WARDROBE_LEVEL, service.GameKv().HookLevelRwd)
}
// SavesV1 方法
//
// @Description: 保存用户KV数据列表。
// @receiver s: sGameKv的实例。
// @return err: 错误信息如果操作成功则为nil。
func (s *sGameKv) SavesV1() (err error) {
// 从Redis列表中获取所有用户KV索引的键
//keys, err := utils.RedisScan("user:kv:*")
err = tools.Redis.RedisScanV2("user:kv:*", func(keys []string) (err error) {
// 定义用于存储用户数据的结构体
type ListData struct {
Uid int64 `json:"uid"`
Kv interface{} `json:"kv"`
}
var list []*ListData
// 初始化列表长度与keys数组一致
list = make([]*ListData, 0)
//需要删除的key
var delKey []string
// 遍历keys获取每个用户的数据并填充到list中
for _, cacheKey := range keys {
//g.Log().Infof(ctx, "保存用户kv数据%v", v)
//uid := v.Int64()
//cacheKey = "user:kv:" + strconv.FormatInt(uid, 10)
result := strings.Split(cacheKey, ":")
var uid int64
uid, err = strconv.ParseInt(result[2], 10, 64)
if err != nil {
g.Log().Error(ctx, err)
g.Redis().Del(ctx, cacheKey)
continue
}
////如果1天没有活跃跳过
//user, _ := service.MemberUser().Info(uid)
//if user.UpdatedAt.Seconds < gtime.Now().Add(consts.ActSaveTime).Unix() {
// continue
//}
get, _ := g.Redis().Get(ctx, cacheKey)
var data interface{}
get.Scan(&data)
list = append(list, &ListData{
Uid: int64(uid),
Kv: data,
})
delKey = append(delKey, cacheKey)
}
// 将列表数据保存到数据库
if len(list) > 0 {
_, err2 := g.Model("game_kv").Batch(30).Data(list).Save()
list = make([]*ListData, 0)
if err2 != nil {
g.Log().Error(ctx, err2)
return
}
//批量删除key
for _, v := range delKey {
_, err2 = g.Redis().Del(ctx, v)
if err2 != nil {
g.Log().Errorf(ctx, "删除存档错误:%v,err=%v", v, err2)
return
}
}
delKey = make([]string, 0)
}
if err != nil {
g.Log().Error(ctx, "当前kv数据入库失败: %v", err)
}
return
})
//if err != nil {
// return err
//}
////跳过
//if len(keys) == 0 {
// return
//}
////一次最多处理10w条
//if len(keys) > 10000 {
// keys = keys[:10000]
//}
return
}

View File

@@ -6,6 +6,7 @@ package logic
import (
_ "github.com/ayflying/utility_go/internal/logic/gameAct"
_ "github.com/ayflying/utility_go/internal/logic/gameKv"
_ "github.com/ayflying/utility_go/internal/logic/ip2region"
_ "github.com/ayflying/utility_go/internal/logic/logData"
_ "github.com/ayflying/utility_go/internal/logic/systemCron"

View File

@@ -3,8 +3,8 @@ package systemCron
import (
"encoding/json"
"fmt"
v1 "github.com/ayflying/utility_go/api/pgk/v1"
"github.com/ayflying/utility_go/pgk/notice"
v1 "github.com/ayflying/utility_go/api/pkg/v1"
"github.com/ayflying/utility_go/pkg/notice"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/gclient"
)

View File

@@ -1,7 +1,7 @@
syntax = "proto3";
package package;
option go_package = "github.com/ayflying/utility_go/api/pgk/v1";
option go_package = "github.com/ayflying/utility_go/api/pkg/v1";
// NoticeType

View File

@@ -1,134 +0,0 @@
package aycache
import (
"context"
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/util/gconv"
"path"
"strings"
"time"
)
type AdapterFile struct {
FilePath string
}
func (a AdapterFile) Set(ctx context.Context, key interface{}, value interface{}, duration time.Duration) error {
//defer a.handleLruKey(ctx, key)
//expireTime := a.getInternalExpire(duration)
//a.data.Set(key, memoryDataItem{
// a: value,
// a: expireTime,
//})
//c.eventList.PushBack(&adapterMemoryEvent{
// k: key,
// e: expireTime,
//})
arr := strings.Split(":", gconv.String(key))
fileName := path.Join(arr...)
return gfile.PutBytes(fileName, gconv.Bytes(value))
}
func (a AdapterFile) SetMap(ctx context.Context, data map[interface{}]interface{}, duration time.Duration) error {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) SetIfNotExist(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (ok bool, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) SetIfNotExistFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) Get(ctx context.Context, key interface{}) (*gvar.Var, error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) GetOrSetFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) GetOrSetFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) Contains(ctx context.Context, key interface{}) (bool, error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) Size(ctx context.Context) (size int, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) Data(ctx context.Context) (data map[interface{}]interface{}, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) Keys(ctx context.Context) (keys []interface{}, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) Values(ctx context.Context) (values []interface{}, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) Update(ctx context.Context, key interface{}, value interface{}) (oldValue *gvar.Var, exist bool, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) UpdateExpire(ctx context.Context, key interface{}, duration time.Duration) (oldDuration time.Duration, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) GetExpire(ctx context.Context, key interface{}) (time.Duration, error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) Remove(ctx context.Context, keys ...interface{}) (lastValue *gvar.Var, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) Clear(ctx context.Context) error {
//TODO implement me
panic("implement me")
}
func (a AdapterFile) Close(ctx context.Context) error {
//TODO implement me
panic("implement me")
}
func NewAdapterFile(filePath string) gcache.Adapter {
return &AdapterFile{
FilePath: filePath,
}
}

View File

@@ -1,15 +0,0 @@
package aycache
import (
"github.com/gogf/gf/v2/os/gcache"
)
var adapterMemoryClient = gcache.New()
// NewAdapterMemory 创建并返回一个新的内存缓存对象。
func NewAdapterMemory() gcache.Adapter {
//if adapterMemoryClient == nil {
// adapterMemoryClient = gcache.New()
//}
return adapterMemoryClient
}

View File

@@ -1,120 +0,0 @@
package aycache
import (
"context"
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/database/gredis"
"github.com/gogf/gf/v2/os/gcache"
"time"
)
// AdapterRedis is the gcache adapter implements using Redis server.
type AdapterMemcached struct {
//redis *gredis.Redis
//client
}
func (a AdapterMemcached) Set(ctx context.Context, key interface{}, value interface{}, duration time.Duration) error {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) SetMap(ctx context.Context, data map[interface{}]interface{}, duration time.Duration) error {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) SetIfNotExist(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (ok bool, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) SetIfNotExistFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) Get(ctx context.Context, key interface{}) (*gvar.Var, error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) GetOrSetFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) GetOrSetFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) Contains(ctx context.Context, key interface{}) (bool, error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) Size(ctx context.Context) (size int, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) Data(ctx context.Context) (data map[interface{}]interface{}, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) Keys(ctx context.Context) (keys []interface{}, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) Values(ctx context.Context) (values []interface{}, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) Update(ctx context.Context, key interface{}, value interface{}) (oldValue *gvar.Var, exist bool, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) UpdateExpire(ctx context.Context, key interface{}, duration time.Duration) (oldDuration time.Duration, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) GetExpire(ctx context.Context, key interface{}) (time.Duration, error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) Remove(ctx context.Context, keys ...interface{}) (lastValue *gvar.Var, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) Clear(ctx context.Context) error {
//TODO implement me
panic("implement me")
}
func (a AdapterMemcached) Close(ctx context.Context) error {
//TODO implement me
panic("implement me")
}
// NewAdapterRedis creates and returns a new memory cache object.
func NewAdapterMemcached(redis *gredis.Redis) gcache.Adapter {
return &AdapterMemcached{}
}

View File

@@ -1,18 +0,0 @@
package aycache
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcache"
)
var adapterRedisClient gcache.Adapter
var adapterRedisCache = gcache.New()
func NewAdapterRedis() gcache.Adapter {
if adapterRedisClient == nil {
adapterRedisClient = gcache.NewAdapterRedis(g.Redis("default"))
adapterRedisCache.SetAdapter(adapterRedisClient)
}
return adapterRedisCache
}

View File

@@ -69,6 +69,10 @@ func (s *Excel) ExcelLoad(ctx context.Context, fileItem *FileItem, mainPath stri
fileBytes := gfile.GetBytes(filepath)
arr, _ := gjson.DecodeToJson(fileBytes)
list := arr.Array()
//排除注释行
list = s.RemoveComments(list, fileItem.Json)
//格式化item格式
if len(fileItem.Items) > 0 {
list = s.itemsFormat(list, fileItem.Items)
@@ -98,105 +102,193 @@ func (s *Excel) ExcelLoad(ctx context.Context, fileItem *FileItem, mainPath stri
return
}
//排除配置中注释行
func (s *Excel) RemoveComments(list []interface{}, json []string) []interface{} {
var temp = make([]interface{}, 0)
// 遍历列表中的每个元素
for _, v2 := range list {
var add = true
// 遍历当前元素的每个键值对
for _, v3 := range v2.(g.Map) {
// 如果字符串中存在//则跳过不写入temp
if gstr.Contains(gconv.String(v3), "//") {
//delKey = append(delKey, k2)
add = false
break
}
}
if add {
temp = append(temp, v2)
}
}
return temp
}
// itemsFormat 格式化列表中的道具字段
// 参数:
// - list: 待处理的列表,包含多个元素,每个元素是一个 g.Map 类型
// - Items: 包含需要处理的道具字段名称的切片
// 返回值:
// - 处理后的列表
func (s *Excel) itemsFormat(list []interface{}, Items []string) []interface{} {
// 遍历列表中的每个元素
for k2, v2 := range list {
// 遍历当前元素的每个键值对
for k3, v3 := range v2.(g.Map) {
// 检查当前键是否在需要处理的道具字段列表中
if gstr.InArray(Items, k3) {
// 检查当前值是否为字符串类型
if _, ok := v3.(string); ok {
// 如果是字符串类型,调用 Spilt2Item 函数将其转换为 [][]int64 类型,并更新到列表中
list[k2].(g.Map)[k3] = Spilt2Item(v3.(string))
} else {
// 如果不是字符串类型,记录错误日志
g.Log().Errorf(gctx.New(), "当前类型断言失败:%v,list=%v", v3, v2)
}
}
}
}
// 返回处理后的列表
return list
}
// itemsMapFormat 将列表中指定字段的道具信息转换为映射格式
// 参数:
// - list: 待处理的列表,包含多个元素,每个元素是一个 g.Map 类型
// - Items: 包含需要处理的道具字段名称的切片
// 返回值:
// - 处理后的列表
func (s *Excel) itemsMapFormat(list []interface{}, Items []string) []interface{} {
// 遍历列表中的每个元素
for k2, v2 := range list {
// 遍历当前元素的每个键值对
for k3, v3 := range v2.(g.Map) {
// 检查当前键是否在需要处理的道具字段列表中
if gstr.InArray(Items, k3) {
// 检查当前值是否为字符串类型
if _, ok := v3.(string); ok {
// 如果是字符串类型,调用 Spilt2Item 函数将其转换为 [][]int64 类型
get := Spilt2Item(v3.(string))
// 调用 Items2Map 函数将 [][]int64 类型的数据转换为映射格式,并更新到列表中
list[k2].(g.Map)[k3] = s.Items2Map(get)
} else {
// 如果不是字符串类型,记录错误日志
g.Log().Errorf(gctx.New(), "当前类型断言失败:%v,list=%v", v3, v2)
}
}
}
}
// 返回处理后的列表
return list
}
// sliceFormat 格式化列表中指定字段为切片格式
// 参数:
// - list: 待处理的列表,包含多个元素,每个元素是一个 g.Map 类型
// - Slice: 一个映射,键为需要处理的字段名,值为目标类型(如 "int", "int64", "float64"
// 返回值:
// - 处理后的列表
func (s *Excel) sliceFormat(list []interface{}, Slice map[string]string) []interface{} {
// 遍历 Slice 映射中的每个键值对
for s1, s2 := range Slice {
// 遍历列表中的每个元素
for k2, v2 := range list {
// 遍历当前元素的每个键值对
for k3, v3 := range v2.(g.Map) {
//判断是否存在
// 判断当前键是否与 Slice 中的键匹配
if s1 != k3 {
// 不匹配则跳过当前循环
continue
}
// 检查当前值是否为空字符串
if gconv.String(v3) == "" {
// 若为空,则将该字段设置为空字符串切片
list[k2].(g.Map)[k3] = []string{}
// 跳过当前循环
continue
}
// 用于存储分割后的字符串切片
var parts []string
//断言是否成功
// 断言当前值是否为字符串类型
if get, ok := v3.(string); !ok {
//g.Log().Errorf(gctx.New(), "当前类型断言失败:%v", v3)
// 若断言失败,将当前值转换为字符串并作为唯一元素存入 parts
parts = []string{gconv.String(v3)}
} else {
// 若为字符串类型,将字符串中的特殊字符替换为 "|"
for _, v := range shadiao {
get = strings.ReplaceAll(get, v, "|")
}
parts = strings.Split(get, "|") // 分割字符串
// 按 "|" 分割字符串
parts = strings.Split(get, "|")
}
// 根据 Slice 映射中的值进行类型转换
switch s2 {
case "int":
// 创建一个长度为 parts 的 int 切片
var temp = make([]int, len(parts))
// 遍历 parts 切片,将每个元素转换为 int 类型
for k, v := range parts {
temp[k], _ = strconv.Atoi(v)
}
// 将转换后的切片存入列表中
list[k2].(g.Map)[k3] = temp
case "int64":
// 创建一个长度为 parts 的 int64 切片
var temp = make([]int64, len(parts))
// 遍历 parts 切片,将每个元素转换为 int64 类型
for k, v := range parts {
temp[k], _ = strconv.ParseInt(v, 10, 64)
}
case "float64":
// 创建一个长度为 parts 的 float64 切片
var temp = make([]float64, len(parts))
// 遍历 parts 切片,将每个元素转换为 float64 类型
for k, v := range parts {
temp[k], _ = strconv.ParseFloat(v, 64)
}
// 将转换后的切片存入列表中
list[k2].(g.Map)[k3] = temp
default:
// 若未匹配到指定类型,直接将 parts 存入列表中
list[k2].(g.Map)[k3] = parts
}
}
}
}
// 返回处理后的列表
return list
}
// jsonFormat 将列表中指定字段的 JSON 字符串解析为 Go 数据结构
// 参数:
// - list: 待处理的列表,包含多个元素,每个元素是一个 g.Map 类型
// - Items: 包含需要处理的 JSON 字段名称的切片
// 返回值:
// - 处理后的列表
func (s *Excel) jsonFormat(list []interface{}, Items []string) []interface{} {
// 遍历列表中的每个元素
for k2, v2 := range list {
// 遍历当前元素的每个键值对
for k3, v3 := range v2.(g.Map) {
// 检查当前键是否在需要处理的 JSON 字段列表中
if gstr.InArray(Items, k3) {
// 检查当前值是否为字符串类型
if _, ok := v3.(string); ok {
// 用于存储解析后的 JSON 数据
var get interface{}
// 将字符串解析为 JSON 数据
json.Unmarshal([]byte(v3.(string)), &get)
// 将解析后的 JSON 数据更新到列表中
list[k2].(g.Map)[k3] = get
} else {
// 如果不是字符串类型,记录错误日志
g.Log().Errorf(gctx.New(), "当前类型断言失败:%v,list=%v", v3, v2)
}
}
}
}
// 返回处理后的列表
return list
}

View File

@@ -1,3 +1,4 @@
//Deprecated: 使用新的 pkg.Pay()
package pay
import (
@@ -27,6 +28,7 @@ type WechatPay struct {
PrivateKey string
}
// Deprecated: pkg.Pay().Wechat()
func Wechat() *WechatPay {
var pay = &WechatPay{}
var err error

View File

@@ -1,119 +0,0 @@
package drive
import (
"context"
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/os/gcache"
"time"
)
type AdapterElasticsearch struct {
//FilePath string
Addresses []string
}
func (a AdapterElasticsearch) Set(ctx context.Context, key interface{}, value interface{}, duration time.Duration) error {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) SetMap(ctx context.Context, data map[interface{}]interface{}, duration time.Duration) error {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) SetIfNotExist(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (ok bool, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) SetIfNotExistFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) Get(ctx context.Context, key interface{}) (*gvar.Var, error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) GetOrSetFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) GetOrSetFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) Contains(ctx context.Context, key interface{}) (bool, error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) Size(ctx context.Context) (size int, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) Data(ctx context.Context) (data map[interface{}]interface{}, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) Keys(ctx context.Context) (keys []interface{}, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) Values(ctx context.Context) (values []interface{}, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) Update(ctx context.Context, key interface{}, value interface{}) (oldValue *gvar.Var, exist bool, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) UpdateExpire(ctx context.Context, key interface{}, duration time.Duration) (oldDuration time.Duration, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) GetExpire(ctx context.Context, key interface{}) (time.Duration, error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) Remove(ctx context.Context, keys ...interface{}) (lastValue *gvar.Var, err error) {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) Clear(ctx context.Context) error {
//TODO implement me
panic("implement me")
}
func (a AdapterElasticsearch) Close(ctx context.Context) error {
//TODO implement me
panic("implement me")
}
func NewAdapterElasticsearch(addresses []string) gcache.Adapter {
return &AdapterElasticsearch{
Addresses: addresses,
}
}

View File

@@ -1,30 +1,34 @@
package pgk
import (
v1 "github.com/ayflying/utility_go/api/pgk/v1"
"github.com/ayflying/utility_go/pgk/aycache"
"github.com/ayflying/utility_go/pgk/notice"
"github.com/ayflying/utility_go/pgk/rank"
"github.com/ayflying/utility_go/pgk/s3"
v1 "github.com/ayflying/utility_go/api/pkg/v1"
"github.com/ayflying/utility_go/pkg/aycache"
"github.com/ayflying/utility_go/pkg/notice"
"github.com/ayflying/utility_go/pkg/rank"
"github.com/ayflying/utility_go/pkg/s3"
"github.com/gogf/gf/v2/os/gcache"
)
var ()
// 统一调用
// Deprecated: 请使用 pkg.Notice() 方法替代。
func Notice(typ v1.NoticeType, host string) notice.MessageV1 {
return notice.New(typ, host)
}
// 统一调用cache
// Deprecated: 请使用 pkg.Cache() 方法替代。
func Cache(_name ...string) gcache.Adapter {
return aycache.New(_name...)
}
// Deprecated: 请使用 pkg.S3() 方法替代。
func S3(_name ...string) *s3.Mod {
return s3.New(_name...)
}
// Deprecated: 请使用 pkg.Rank() 方法替代。
func Rank() *rank.Mod {
return rank.New()
}

View File

@@ -2,7 +2,7 @@ package rank
import (
"fmt"
v1 "github.com/ayflying/utility_go/api/pgk/v1"
v1 "github.com/ayflying/utility_go/api/pkg/v1"
"time"
"github.com/gogf/gf/v2/database/gredis"
@@ -46,6 +46,8 @@ func (s *Mod) Load() {
// 返回值:
//
// *F64CountRank: 返回一个指向新创建的F64CountRank实例的指针
// Deprecated: pgk.Rnak().CreateF64CountRank("赛季")
func (s *Mod) CreateF64CountRank(name string) *F64CountRank {
// 初始化F64CountRank实例的name和updateTs字段
// name字段用于标识排行榜的名称格式为"rank:<name>:score"

View File

@@ -1,8 +1,8 @@
package aycache
import (
"github.com/ayflying/utility_go/package/aycache/drive"
drive2 "github.com/ayflying/utility_go/pgk/aycache/drive"
"github.com/ayflying/utility_go/pkg/aycache/drive"
drive2 "github.com/ayflying/utility_go/pkg/aycache/drive"
"github.com/gogf/gf/v2/os/gcache"
)

189
pkg/config/config.go Normal file
View File

@@ -0,0 +1,189 @@
package config
import (
"fmt"
"github.com/apolloconfig/agollo/v4"
apolloConfig "github.com/apolloconfig/agollo/v4/env/config"
"github.com/apolloconfig/agollo/v4/storage"
"github.com/gogf/gf/contrib/config/apollo/v2"
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gres"
"github.com/gogf/gf/v2/text/gstr"
"sync"
)
var (
//ApolloCfg *apolloConfig.AppConfig
ApolloCfg *apollo.Config
ApolloListener []string
Item2Obj = map[string]Load{}
)
// load接口定义了Load方法用于加载数据
type Load interface {
Load(cfg ...string)
}
func NewV1() *Cfg {
return &Cfg{}
}
type Cfg struct {
Lock sync.Mutex
}
func (c *Cfg) GetDbFile(name string) (res *g.Var, err error) {
get2, err := g.Model("game_config").
Where("name", name).Master().Value("data")
err = get2.Scan(&res)
if res == nil {
res = &gvar.Var{}
}
return
}
func (c *Cfg) GetFile(filename string, obj ...Load) (jsonObj *gjson.Json, err error) {
pathStr := "manifest/game/"
filePath := pathStr + filename + ".json"
//err := gres.Load(pathStr + filename)
//载入静态资源到文件对象
err = gres.Load(filePath)
var bytes []byte
if gfile.IsFile(filePath) {
bytes = gfile.GetBytes(filePath)
} else {
bytes = gres.GetContent(filePath)
}
jsonObj, err = gjson.DecodeToJson(bytes)
//g.Dump(filePath, jsonObj)
return
}
// getUrlFile 获取远程配置
func (c *Cfg) GetUrlFile(name string) (jsonObj *gjson.Json, err error) {
urlStr := fmt.Sprintf("http://sdf.sdfs.sdf/%s.json", name)
getUrl, err := g.Client().Discovery(nil).Get(nil, urlStr)
bytes := getUrl.ReadAll()
jsonObj, err = gjson.DecodeToJson(bytes)
return
}
// 获取阿波罗
//func (c *Cfg) GetApollo(name string, obj Load) (jsonObj *gjson.Json, err error) {
// jsonObj, err = c.GetApolloV2(name, obj)
// return
//
// //c.Lock.Lock()
// //defer c.Lock.Unlock()
// //
// //Item2Obj[name+".json"] = obj
// //var cfg = apolloConfig.AppConfig{
// // AppID: ApolloCfg.AppID,
// // Cluster: ApolloCfg.Cluster,
// // IP: ApolloCfg.IP,
// // NamespaceName: name + ".json",
// // Secret: ApolloCfg.Secret,
// // IsBackupConfig: ApolloCfg.IsBackupConfig,
// // BackupConfigPath: ApolloCfg.BackupConfigPath,
// // SyncServerTimeout: 60,
// // MustStart: true,
// //}
// ////cfg.NamespaceName = name + ".json"
// //
// //client, err := agollo.StartWithConfig(func() (*apolloConfig.AppConfig, error) {
// // return ApolloCfg, nil
// //})
// //if client == nil {
// // return
// //}
// //var getStr string
// //var getApollo *storage.Config
// //for range 5 {
// // getApollo = client.GetConfig(cfg.NamespaceName)
// // if getApollo != nil {
// // break
// // }
// // time.Sleep(time.Second * 5)
// //}
// //
// //if getApollo != nil {
// // getStr = getApollo.GetValue("content")
// // if getStr != "" {
// // //写入配置
// // gfile.PutContents(path.Join("manifest", "game", name+".json"), getStr)
// // }
// //} else {
// // jsonObj, err = c.GetFile(name)
// //}
// //jsonObj, err = gjson.DecodeToJson(getStr)
// ////首次运行加入监听器
// //if !gstr.InArray(ApolloListener, name) {
// // c2 := &CustomChangeListener{}
// // client.AddChangeListener(c2)
// // ApolloListener = append(ApolloListener, name)
// //}
// //return
//}
func (c *Cfg) GetApollo(name string, obj Load) (jsonObj *gjson.Json, err error) {
Item2Obj[name+".json"] = obj
// 接入阿波罗配置
ApolloCfg.NamespaceName = name + ".json"
adapter, err := apollo.New(nil, *ApolloCfg)
if err != nil {
g.Log().Fatalf(nil, `%+v`, err)
}
// Change the adapter of default configuration instance.
g.Cfg(name).SetAdapter(adapter)
//首次运行加入监听器
if !gstr.InArray(ApolloListener, name+".json") {
//放置监听器
client, _ := agollo.StartWithConfig(func() (*apolloConfig.AppConfig, error) {
return &apolloConfig.AppConfig{
AppID: ApolloCfg.AppID,
Cluster: ApolloCfg.Cluster,
NamespaceName: ApolloCfg.NamespaceName,
IP: ApolloCfg.IP,
IsBackupConfig: ApolloCfg.IsBackupConfig,
BackupConfigPath: ApolloCfg.BackupConfigPath,
Secret: ApolloCfg.Secret,
SyncServerTimeout: ApolloCfg.SyncServerTimeout,
MustStart: ApolloCfg.MustStart,
}, nil
})
c2 := &CustomChangeListener{}
client.AddChangeListener(c2)
ApolloListener = append(ApolloListener, name+".json")
}
cfg, err := g.Cfg(name).Get(nil, "content")
cfg.Scan(&jsonObj)
return
}
// 阿波罗监听器
type CustomChangeListener struct {
wg sync.WaitGroup
}
func (c *CustomChangeListener) OnChange(changeEvent *storage.ChangeEvent) {
g.Log().Debugf(nil, "当前Namespace变化了%v", changeEvent.Namespace)
filename := changeEvent.Namespace
if obj, ok := Item2Obj[filename]; ok {
//重载配置文件
obj.Load(changeEvent.Changes["content"].NewValue.(string))
}
}
func (c *CustomChangeListener) OnNewestChange(event *storage.FullChangeEvent) {
//write your code here
}

View File

@@ -33,7 +33,6 @@ func New(name ...string) *elastic {
return &elastic{
client: es,
}
}
// createIndex 创建索引

View File

@@ -1,8 +1,8 @@
package notice
import (
v1 "github.com/ayflying/utility_go/api/pgk/v1"
"github.com/ayflying/utility_go/pgk/notice/drive"
v1 "github.com/ayflying/utility_go/api/pkg/v1"
"github.com/ayflying/utility_go/pkg/notice/drive"
)
type MessageV1 interface {

40
pkg/pkg.go Normal file
View File

@@ -0,0 +1,40 @@
package pkg
import (
v1 "github.com/ayflying/utility_go/api/pkg/v1"
"github.com/ayflying/utility_go/pkg/aycache"
"github.com/ayflying/utility_go/pkg/config"
"github.com/ayflying/utility_go/pkg/notice"
"github.com/ayflying/utility_go/pkg/rank"
"github.com/ayflying/utility_go/pkg/s3"
"github.com/ayflying/utility_go/pkg/websocket"
"github.com/gogf/gf/v2/os/gcache"
)
var ()
// 统一调用
func Notice(typ v1.NoticeType, host string) notice.MessageV1 {
return notice.New(typ, host)
}
// 统一调用cache
func Cache(_name ...string) gcache.Adapter {
return aycache.New(_name...)
}
func S3(_name ...string) *s3.Mod {
return s3.New(_name...)
}
func Rank() *rank.Mod {
return rank.New()
}
func Websocket() *websocket.SocketV1 {
return websocket.NewV1()
}
func Config() *config.Cfg {
return config.NewV1()
}

View File

@@ -2,6 +2,7 @@ package rank
import (
"fmt"
v1 "github.com/ayflying/utility_go/api/pkg/v1"
"time"
"github.com/gogf/gf/v2/database/gredis"
@@ -21,14 +22,14 @@ type F64CountRank struct {
updateTs string // 更新时间key
}
type RankData struct {
Id int64
Score int64
Rank int32
UpdateTs int64
}
//
//type RankData struct {
// Id int64
// Score int64
// Rank int32
// UpdateTs int64
//}
// Deprecated:Use pgk.Rank()
func New() *Mod {
return &Mod{}
}
@@ -45,8 +46,6 @@ func (s *Mod) Load() {
// 返回值:
//
// *F64CountRank: 返回一个指向新创建的F64CountRank实例的指针
//
// Deprecated:Use pgk.Rank().CreateF64CountRank(fmt.Sprintf("rank:%v", 1))
func (s *Mod) CreateF64CountRank(name string) *F64CountRank {
// 初始化F64CountRank实例的name和updateTs字段
// name字段用于标识排行榜的名称格式为"rank:<name>:score"
@@ -321,7 +320,7 @@ func (r *F64CountRank) UpdateScore(id int64, score int64) (err error) {
//
// list - 排名信息列表
// err - 错误信息,如果执行过程中遇到错误
func (r *F64CountRank) GetRankInfosNotTs(offset, count int) (list []*RankData, err error) {
func (r *F64CountRank) GetRankInfosNotTs(offset, count int) (list []*v1.RankData, err error) {
// 初始化存储成员ID的切片
var members []int64
@@ -341,7 +340,7 @@ func (r *F64CountRank) GetRankInfosNotTs(offset, count int) (list []*RankData, e
}
// 根据获取的成员ID数量初始化排名信息列表
list = make([]*RankData, len(members))
list = make([]*v1.RankData, len(members))
for i := range members {
// 获取当前成员ID
id := members[i]
@@ -361,9 +360,9 @@ func (r *F64CountRank) GetRankInfosNotTs(offset, count int) (list []*RankData, e
// 返回值:
//
// rankInfo - 包含id的分数和排名信息的指针如果没有找到则返回nil
func (r *F64CountRank) GetIdRankNotTs(id int64) (rankInfo *RankData) {
func (r *F64CountRank) GetIdRankNotTs(id int64) (rankInfo *v1.RankData) {
// 初始化rankInfo结构体设置id其他字段将通过查询填充
rankInfo = &RankData{Id: id}
rankInfo = &v1.RankData{Id: id}
// 查询有序集合中指定id的分数
score, err := g.Redis().ZScore(ctx, r.name, id)

View File

@@ -0,0 +1,16 @@
package websocket
import "context"
// 定义一个处理方法的类型
type Handler func(ctx context.Context, req any) (err error)
// 路由器的处理映射
var (
handlers = make(map[int]Handler)
)
// 注册方法将某个消息路由器ID和对应的处理方法关联起来
func (s *SocketV1) RegisterRouter(cmd int, handler Handler) {
handlers[cmd] = handler
}

179
pkg/websocket/socket_new.go Normal file
View File

@@ -0,0 +1,179 @@
package websocket
import (
"context"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/util/gconv"
"github.com/google/uuid"
"github.com/gorilla/websocket"
"sync"
"github.com/gogf/gf/v2/net/ghttp"
)
type SocketV1 struct{}
var (
//ctx = gctx.New()
//Conn map[uuid.UUID]*WebsocketData
lock sync.Mutex
m = gmap.New(true)
)
type WebsocketData struct {
Ws *websocket.Conn
Uuid uuid.UUID
Uid int64
Ctx context.Context
}
func NewV1() *SocketV1 {
return &SocketV1{}
}
type SocketInterface interface {
OnConnect(*websocket.Conn)
OnMessage(*WebsocketData, []byte, int)
Send(uuid.UUID, []byte) (err error)
SendAll(data []byte)
OnClose(conn *websocket.Conn)
}
func (s *SocketV1) Load(serv *ghttp.Server, prefix string) {
//websocket服务启动
serv.Group(prefix, func(group *ghttp.RouterGroup) {
var websocketCfg = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
group.Bind(
func(r *ghttp.Request) {
ctx := r.Context()
ws, err := websocketCfg.Upgrade(r.Response.Writer, r.Request, nil)
if err != nil {
glog.Error(ctx, err)
r.Exit()
}
//ws联机触发器
NewV1().OnConnect(ctx, ws)
},
)
})
}
// OnConnect
//
// @Description:
// @receiver s
// @param conn
func (s *SocketV1) OnConnect(ctx context.Context, conn *websocket.Conn) {
//lock.Lock()
//defer lock.Unlock()
defer conn.Close()
id, _ := uuid.NewUUID()
ip := conn.RemoteAddr().String()
data := &WebsocketData{
Uuid: id,
Ws: conn,
Ctx: ctx,
}
m.Set(id, data)
//defer delete(Conn, id)
//to := fmt.Sprintf("创建连接:%v,ip=%v", id, ip)
//s.Send(id, []byte(to))
for {
//进入当前连接线程拥堵
msgType, msg, err := conn.ReadMessage()
if err != nil {
//客户端断开返回错误,断开当前连接
break
}
s.OnMessage(m.Get(id).(*WebsocketData), msg, msgType)
}
//关闭连接触发
s.OnClose(id, conn)
g.Log().Debugf(ctx, "断开连接:uuid=%v,ip=%v", id, ip)
}
// OnMessage
//
// @Description:
// @receiver s
// @param msg
// @param msgType
func (s *SocketV1) OnMessage(conn *WebsocketData, req []byte, msgType int) {
//g.Log().Debugf(ctx, "收到消息:%v,type=%v,conn=%v", string(req), msgType, conn)
//s.Send(conn.Uuid, msg)
//s.SendAll(msg)
msgStr := string(req)
msg := msgStr[8:]
cmd := gconv.Int(msgStr[:8])
//GetRouter(cmd, conn.Uid, msg)
handler, exist := handlers[cmd]
if exist {
//匹配上路由器
handler(conn.Ctx, msg)
} else {
//fmt.Println("未注册的路由器ID:", cmd)
s.Send(conn.Uuid, []byte("未注册的协议号:"+msgStr[:8]))
s.OnClose(conn.Uuid, conn.Ws)
return
}
}
// Send
//
// @Description:
// @receiver s
// @param uid
// @param data
// @return err
func (s *SocketV1) Send(id uuid.UUID, data []byte) (err error) {
if !m.Contains(id) {
return
}
conn := m.Get(id).(*WebsocketData)
conn.Ws.WriteMessage(1, data)
return
}
// 批量发送
func (s *SocketV1) SendAll(data []byte) {
m.Iterator(func(k interface{}, v interface{}) bool {
//fmt.Printf("%v:%v ", k, v)
conn := v.(*WebsocketData)
conn.Ws.WriteMessage(1, data)
return true
})
}
// OnClose
//
// @Description:
// @receiver s
// @param conn
func (s *SocketV1) OnClose(id uuid.UUID, conn *websocket.Conn) {
// 在此处编写断开连接后的处理逻辑
g.Log().Debugf(gctx.New(), "WebSocket connection from %s has been closed.", conn.RemoteAddr())
// 可能的后续操作:
// 1. 更新连接状态或从连接池移除
// 2. 发送通知或清理关联资源
// 3. 执行特定于业务的断开处理
m.Remove(id)
conn.Close()
}

32
service/game_kv.go Normal file
View File

@@ -0,0 +1,32 @@
// ================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// You can delete these comments if you wish manually maintain this interface file.
// ================================================================================
package service
type (
IGameKv interface {
// SavesV1 方法
//
// @Description: 保存用户KV数据列表。
// @receiver s: sGameKv的实例。
// @return err: 错误信息如果操作成功则为nil。
SavesV1() (err error)
}
)
var (
localGameKv IGameKv
)
func GameKv() IGameKv {
if localGameKv == nil {
panic("implement not found for interface IGameKv, forgot register?")
}
return localGameKv
}
func RegisterGameKv(i IGameKv) {
localGameKv = i
}

View File

@@ -15,7 +15,7 @@ type randMod struct {
// RandomAll 按权重随机选取 N 个不重复的元素
func (m *randMod) RandomAll(data map[int]int, n int) []int {
if n > len(data) {
return nil
n = len(data)
}
rand.Seed(time.Now().UnixNano())
// 复制权重映射,避免修改原始数据

View File

@@ -223,3 +223,33 @@ func ReverseSlice[T comparable](s []T) []T {
}
return s
}
// 道具数量合并
func (m *tools) ItemsMerge(_items ...[][]int64) [][]int64 {
var items [][]int64
for _, v := range _items {
items = append(items, v...)
}
if len(items) == 0 {
return [][]int64{}
}
var temp = make(map[int64]int64)
for _, v := range items {
if len(v) < 2 {
g.Log().Errorf(ctx, "分解的物品格式不对:%v", v)
continue
}
if _, ok := temp[v[0]]; !ok {
temp[v[0]] = 0
}
temp[v[0]] += v[1]
}
items = make([][]int64, len(temp))
i := 0
for k, v := range temp {
items[i] = []int64{k, v}
i++
}
return items
}