diff --git a/.vscode/launch.json b/.vscode/launch.json index 868a03586..73988f5b7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -29,6 +29,19 @@ "output": "${workspaceFolder}/bin/vsdebug_gate", //设置vscode调试时生成文件的路径 "showGlobalVariables": true, "env": {}, //可以用来配置调试启动时所用的环境变量参数,比如gopath临时设置为某个参数就可以在这里指定,如果有多个gopath,用英文冒号:来连接多个gopath + }, + { + "name": "worker_1", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/services/worker", //配置Go项目启动文件路径,即main函数所在的.go文件的路径,${workspaceRoot}代表项目的根目录,也就是 /bin /pkg /src这三个文件夹所在的目录 + "args": ["-conf","./conf/worker_1.yaml"], + "cwd": "${workspaceFolder}/bin", //设置工作目录 + "internalConsoleOptions": "openOnSessionStart", + "output": "${workspaceFolder}/bin/vsdebug_worker", //设置vscode调试时生成文件的路径 + "showGlobalVariables": true, + "env": {}, //可以用来配置调试启动时所用的环境变量参数,比如gopath临时设置为某个参数就可以在这里指定,如果有多个gopath,用英文冒号:来连接多个gopath } ] } \ No newline at end of file diff --git a/bin/conf/worker_1.yaml b/bin/conf/worker_1.yaml new file mode 100644 index 000000000..87dd0d669 --- /dev/null +++ b/bin/conf/worker_1.yaml @@ -0,0 +1,28 @@ +id : "worker_1" #服务的唯一id 在集群服务下不能重复即可 建议配置文件名与服务id一致 +ip : "172.0.0.1" #运行主机Ip 集群通信中 按ip节点通行的查询字段 此字段可以注释掉 注释后取当前运行主机公网ip地址 +port : 9568 #服务监听端口 RPC服务 +tag : "demo" #服务集群标签 相同标签 且sys.registry 和 sys.rpc 配置一致 即可互相发现和通信 +type : "dreamfactory" #服务类型 相同服务类型相同 如 多个login 服务 相同服务多开 服务类型一致 +category : "BusinessService" #服务类别 例如 网关服务器 或者 游戏服务器 以及普通业务服务器 +version : 1.0 #服务版本 多服务器相同的服务类型 高版本比低版本拥有更高的访问优先级 使用场景 热更新机制 + +#系统配置 +sys: + log: #日志系统 + FileName: "./log/worker_1.log" #日志文件存放地址 + Loglevel: 0 #日志文件输出级别 + LogMaxSize: 128 #日志文件最大Size + LogMaxAge: 7 #日志文件最多保留天数 + registry: #注册表系统 服务发现 + RegistryType: 0 #服务发现系统 0 Consul 组件 + Consul_Addr: "10.0.0.9:8500" + Consul_RegisterInterval: 5 + Consul_RegisterTTL: 7 + cache: #缓存系统 + Redis_Addr: ["10.0.0.9:9001","10.0.0.9:9002","10.0.0.9:9003","10.0.1.45:9004","10.0.1.45:9005","10.0.1.45:9006"] + Redis_Password: "" + +#模块配置 +modules: + SM_WebModule: + Port: 9898 diff --git a/bin/log/worker_1.log b/bin/log/worker_1.log new file mode 100644 index 000000000..0064446a7 --- /dev/null +++ b/bin/log/worker_1.log @@ -0,0 +1,9 @@ +2022/05/30 18:28:38.741 info rpcx/service.go:90 Sys log Init success ! +2022/05/30 18:28:38.758 info rpcx/service.go:95 Sys event Init success ! +2022/05/30 18:28:38.758 info rpcx/service.go:100 Sys registry Init success ! +2022/05/30 18:28:38.758 info rpcx/service.go:105 Sys rpcx Init success ! +2022/05/30 18:28:38.763 info services/servicebase.go:20 init sys.cache success! +2022/05/30 18:28:38.763 info cbase/servicebase.go:58 服务[worker_1] 初始化完成! +2022/05/30 18:28:38.763 info cbase/servicebase.go:80 服务[worker_1:1.0.0.0] 启动完成! +2022/05/30 18:28:38.764 debug m_comps/gate_comp.go:74 RegisterFunctionName:Login +2022/05/30 18:28:38.766 info registry/consul.go:253 发现新的服务【worker_1:1.0.0.0】 diff --git a/comm/core.go b/comm/core.go index 583aa9189..f01e3ac1f 100644 --- a/comm/core.go +++ b/comm/core.go @@ -2,7 +2,40 @@ package comm import "github.com/liwei1dao/lego/core" +const ( + SC_ServiceGateRouteComp core.S_Comps = "SC_GateRouteComp" //s_comps.ISC_GateRouteComp +) + const ( SM_GateModule core.M_Modules = "SM_GateModule" //gate模块 网关服务模块 SM_WebModule core.M_Modules = "SM_WebModule" //web模块 ) + +const ( //Rpc + Rpc_GateRoute core.Rpc_Key = "Rpc_GateRoute" //网关路由 +) + +type ISC_GateRouteComp interface { + core.IServiceComp + RegisterRoute() +} + +//用户会话 +type IUserSession interface { + GetSessionId() string + GetIP() string + GetGateId() string + SendMsg(ServiceMethod string, msg interface{}) (err error) + Close() (err error) +} + +//消息体 +type MessageHead struct { + ServiceMethod string //服务名 +} + +//处理JSON消息 +type Message struct { + Head *MessageHead + Data []byte +} diff --git a/comm/message.go b/comm/message.go new file mode 100644 index 000000000..9d28c497b --- /dev/null +++ b/comm/message.go @@ -0,0 +1 @@ +package comm diff --git a/go.mod b/go.mod index 7a44b5d4b..f2807f361 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,10 @@ module go_dreamfactory go 1.18 -require github.com/liwei1dao/lego v0.0.0-20220530082438-d1a47a89b5d1 +require ( + github.com/liwei1dao/lego v0.0.0-20220530082438-d1a47a89b5d1 + google.golang.org/protobuf v1.28.0 +) require ( github.com/akutz/memconn v0.1.0 // indirect @@ -98,7 +101,6 @@ require ( golang.org/x/text v0.3.7 // indirect golang.org/x/tools v0.1.10 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/protobuf v1.28.0 // indirect gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/modules/gate/module.go b/modules/gate/module.go index eda1848b4..06beaa52c 100644 --- a/modules/gate/module.go +++ b/modules/gate/module.go @@ -2,9 +2,9 @@ package gate import ( "go_dreamfactory/comm" + "go_dreamfactory/modules" "github.com/liwei1dao/lego/core" - "github.com/liwei1dao/lego/core/cbase" "github.com/liwei1dao/lego/sys/log" ) @@ -14,7 +14,7 @@ func NewModule() core.IModule { } type Gate struct { - cbase.ModuleBase + modules.ModuleBase options *Options } diff --git a/modules/m_comps/gate_comp.go b/modules/m_comps/gate_comp.go new file mode 100644 index 000000000..cc406e7ca --- /dev/null +++ b/modules/m_comps/gate_comp.go @@ -0,0 +1,111 @@ +package m_comps + +import ( + "context" + "reflect" + "unicode" + "unicode/utf8" + + "github.com/liwei1dao/lego/base" + "github.com/liwei1dao/lego/core" + "github.com/liwei1dao/lego/core/cbase" + "github.com/liwei1dao/lego/sys/log" +) + +var typeOfContext = reflect.TypeOf((*context.Context)(nil)).Elem() +var typeOfError = reflect.TypeOf((*error)(nil)).Elem() + +/* +模块 网关组件 接收处理用户传递消息 +*/ +type MComp_GateComp struct { + cbase.ModuleCompBase + service base.IRPCXService +} + +func (this *MComp_GateComp) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) { + this.ModuleCompBase.Init(service, module, comp, options) + this.service = service.(base.IRPCXService) + this.suitableMethods(reflect.TypeOf(comp)) + return +} + +// func (this *MComp_GateComp) Start() (err error) { +// if err = this.ModuleCompBase.Start(); err != nil { +// return +// } +// isRegisterLocalRoute := false +// //注册本地路由 + +// //注册远程路由 +// cc, e := this.service.GetComp(comm.SC_ServiceGateRouteComp) +// if e == nil { +// cc.(comm.ISC_GateRouteComp).RegisterRoute(this.ComId, this.comp.ReceiveMsg) +// isRegisterLocalRoute = true +// } + +// if !isRegisterLocalRoute { +// return fmt.Errorf("MC_GateComp 未成功注册路由!") +// } +// return +// } + +func (this *MComp_GateComp) suitableMethods(typ reflect.Type) { + for m := 0; m < typ.NumMethod(); m++ { + method := typ.Method(m) + mtype := method.Type + mname := method.Name + // Method must be exported. + if method.PkgPath != "" { + continue + } + // Method needs four ins: receiver, context.Context, *args, *reply. + if mtype.NumIn() != 4 { + continue + } + // First arg must be context.Context + ctxType := mtype.In(1) + if !ctxType.Implements(typeOfContext) { + continue + } + + // Second arg need not be a pointer. + argType := mtype.In(2) + if !this.isExportedOrBuiltinType(argType) { + continue + } + // Third arg must be a pointer. + replyType := mtype.In(3) + if replyType.Kind() != reflect.Ptr { + continue + } + // Reply type must be exported. + if !this.isExportedOrBuiltinType(replyType) { + continue + } + // Method needs one out. + if mtype.NumOut() != 1 { + continue + } + // The return type of the method must be error. + if returnType := mtype.Out(0); returnType != typeOfError { + continue + } + log.Debugf("RegisterFunctionName:%s", mname) + this.service.RegisterFunctionName(mname, method) + } +} + +func (this *MComp_GateComp) isExportedOrBuiltinType(t reflect.Type) bool { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + // PkgPath will be non-empty even for an exported type, + // so we need to check the type name as well. + return this.isExported(t.Name()) || t.PkgPath() == "" +} + +func (this *MComp_GateComp) isExported(name string) bool { + rune, _ := utf8.DecodeRuneInString(name) + return unicode.IsUpper(rune) +} diff --git a/modules/modulebase.go b/modules/modulebase.go new file mode 100644 index 000000000..c8fb7cbab --- /dev/null +++ b/modules/modulebase.go @@ -0,0 +1,9 @@ +package modules + +import ( + "github.com/liwei1dao/lego/core/cbase" +) + +type ModuleBase struct { + cbase.ModuleBase +} diff --git a/modules/web/module.go b/modules/web/module.go index 2b9e46fa7..50d88ec37 100644 --- a/modules/web/module.go +++ b/modules/web/module.go @@ -2,39 +2,42 @@ package web import ( "go_dreamfactory/comm" + "go_dreamfactory/modules" "github.com/liwei1dao/lego/core" - "github.com/liwei1dao/lego/core/cbase" - "github.com/liwei1dao/lego/sys/log" ) func NewModule() core.IModule { - m := new(Gate) + m := new(Web) return m } -type Gate struct { - cbase.ModuleBase - options *Options +type Web struct { + modules.ModuleBase + options *Options + user_comp *User_Comp } -func (this *Gate) GetType() core.M_Modules { +func (this *Web) GetType() core.M_Modules { return comm.SM_WebModule } -func (this *Gate) NewOptions() (options core.IModuleOptions) { +func (this *Web) NewOptions() (options core.IModuleOptions) { return new(Options) } -func (this *Gate) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) { +func (this *Web) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) { err = this.ModuleBase.Init(service, module, options) this.options = options.(*Options) - log.Debugf("Module.Gate Init") return } -func (this *Gate) Start() (err error) { +func (this *Web) Start() (err error) { err = this.ModuleBase.Start() - log.Debugf("Module.Gate Start") return } + +func (this *Web) OnInstallComp() { + this.ModuleBase.OnInstallComp() + this.user_comp = this.RegisterComp(new(User_Comp)).(*User_Comp) +} diff --git a/modules/web/user_comp.go b/modules/web/user_comp.go new file mode 100644 index 000000000..22159d446 --- /dev/null +++ b/modules/web/user_comp.go @@ -0,0 +1,24 @@ +package web + +import ( + "context" + "go_dreamfactory/comm" + "go_dreamfactory/modules/m_comps" + "go_dreamfactory/pb" + + "github.com/liwei1dao/lego/core" +) + +type User_Comp struct { + m_comps.MComp_GateComp +} + +func (this *User_Comp) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) { + this.MComp_GateComp.Init(service, module, comp, options) + return +} + +func (t *User_Comp) Login(ctx context.Context, req comm.IUserSession, rsp *pb.UserLoginReq) error { + + return nil +} diff --git a/pb/proto/comm.proto b/pb/proto/comm.proto index fbeb20245..f3d2253e6 100644 --- a/pb/proto/comm.proto +++ b/pb/proto/comm.proto @@ -1,2 +1,3 @@ syntax = "proto3"; -option go_package = ".;pb"; \ No newline at end of file +option go_package = ".;pb"; + diff --git a/pb/proto/user_msg.proto b/pb/proto/user_msg.proto new file mode 100644 index 000000000..b7c8960b7 --- /dev/null +++ b/pb/proto/user_msg.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; +option go_package = ".;pb"; + +message UserLoginReq { + string Name = 1; +} +message UserLoginResp { + int32 Code = 1; +} diff --git a/pb/user_msg.pb.go b/pb/user_msg.pb.go new file mode 100644 index 000000000..77e09793f --- /dev/null +++ b/pb/user_msg.pb.go @@ -0,0 +1,203 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.0 +// protoc v3.20.0 +// source: user_msg.proto + +package pb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type UserLoginReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` +} + +func (x *UserLoginReq) Reset() { + *x = UserLoginReq{} + if protoimpl.UnsafeEnabled { + mi := &file_user_msg_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UserLoginReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserLoginReq) ProtoMessage() {} + +func (x *UserLoginReq) ProtoReflect() protoreflect.Message { + mi := &file_user_msg_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserLoginReq.ProtoReflect.Descriptor instead. +func (*UserLoginReq) Descriptor() ([]byte, []int) { + return file_user_msg_proto_rawDescGZIP(), []int{0} +} + +func (x *UserLoginReq) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type UserLoginResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Code int32 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"` +} + +func (x *UserLoginResp) Reset() { + *x = UserLoginResp{} + if protoimpl.UnsafeEnabled { + mi := &file_user_msg_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UserLoginResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserLoginResp) ProtoMessage() {} + +func (x *UserLoginResp) ProtoReflect() protoreflect.Message { + mi := &file_user_msg_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserLoginResp.ProtoReflect.Descriptor instead. +func (*UserLoginResp) Descriptor() ([]byte, []int) { + return file_user_msg_proto_rawDescGZIP(), []int{1} +} + +func (x *UserLoginResp) GetCode() int32 { + if x != nil { + return x.Code + } + return 0 +} + +var File_user_msg_proto protoreflect.FileDescriptor + +var file_user_msg_proto_rawDesc = []byte{ + 0x0a, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6d, 0x73, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x22, 0x22, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, + 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x23, 0x0a, 0x0d, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x3b, 0x70, + 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_user_msg_proto_rawDescOnce sync.Once + file_user_msg_proto_rawDescData = file_user_msg_proto_rawDesc +) + +func file_user_msg_proto_rawDescGZIP() []byte { + file_user_msg_proto_rawDescOnce.Do(func() { + file_user_msg_proto_rawDescData = protoimpl.X.CompressGZIP(file_user_msg_proto_rawDescData) + }) + return file_user_msg_proto_rawDescData +} + +var file_user_msg_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_user_msg_proto_goTypes = []interface{}{ + (*UserLoginReq)(nil), // 0: UserLoginReq + (*UserLoginResp)(nil), // 1: UserLoginResp +} +var file_user_msg_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 + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_user_msg_proto_init() } +func file_user_msg_proto_init() { + if File_user_msg_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_user_msg_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UserLoginReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_user_msg_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UserLoginResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_user_msg_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_user_msg_proto_goTypes, + DependencyIndexes: file_user_msg_proto_depIdxs, + MessageInfos: file_user_msg_proto_msgTypes, + }.Build() + File_user_msg_proto = out.File + file_user_msg_proto_rawDesc = nil + file_user_msg_proto_goTypes = nil + file_user_msg_proto_depIdxs = nil +} diff --git a/pb_2.7.py b/pb_2.7.py new file mode 100644 index 000000000..b86aebc6b --- /dev/null +++ b/pb_2.7.py @@ -0,0 +1,29 @@ +import io +import os +import re + +def buildProto(pbpath,outpath,pbfile): + cmdstr = 'protoc.exe --go_out={0} -I{1} {1}/{2}.proto'.format(outpath,pbpath,pbfile) + os.system(cmdstr) + file_data = "" + tags = {} + tagsstr = "" + file = "{0}/{1}.pb.go".format(outpath,pbfile) + with io.open(file, "r", encoding='utf-8') as f: + for line in f: + if 'tags:' in line: + for v in re.findall(r"`(.+?)`",line)[0].split(' '): + tag = v.split(':') + tags[tag[0]] = tag[1] + for v in re.findall(r"tags:{(.+?)}",line)[0].split(' '): + tag = v.split(':') + tags[tag[0]] = tag[1] + for key,value in tags.items(): + tagsstr += "{0}:{1} ".format(key,value) + line = re.sub(r"`(.+?)`", "`{0}`".format(tagsstr[0:len(tagsstr)-1]), line) + file_data += line + with io.open(file,"w",encoding='utf-8') as f: + f.write(file_data) + + +buildProto('./pb/proto','./pb','user_msg') \ No newline at end of file diff --git a/services/s_comps/comp_gateroute.go b/services/s_comps/comp_gateroute.go new file mode 100644 index 000000000..00dae8dca --- /dev/null +++ b/services/s_comps/comp_gateroute.go @@ -0,0 +1,36 @@ +package s_comps + +import ( + "fmt" + + "github.com/liwei1dao/lego/base" + "github.com/liwei1dao/lego/core" + "github.com/liwei1dao/lego/core/cbase" +) + +type SComp_GateRouteComp struct { + cbase.ServiceCompBase + Service base.IRPCXService +} + +func (this *SComp_GateRouteComp) Init(service core.IService, comp core.IServiceComp, options core.ICompOptions) (err error) { + if s, ok := service.(base.IRPCXService); !ok { + return fmt.Errorf("SC_GateRouteComp Init service is no IRPCXService") + } else { + this.Service = s + } + err = this.ServiceCompBase.Init(service, comp, options) + + return err +} + +func (this *SComp_GateRouteComp) Start() (err error) { + err = this.ServiceCompBase.Start() + // this.Service.RegisterFunctionName(string(comm.Rpc_GateRoute), this.ReceiveMsg) //注册网关路由接收接口 + return +} + +// func (this *SComp_GateRouteComp) ReceiveMsg(ctx context.Context, args comm.IUserMessage, reply *Reply) error { + +// return nil +// } diff --git a/services/worker/main.go b/services/worker/main.go index 8e528bc0a..10f7bec5a 100644 --- a/services/worker/main.go +++ b/services/worker/main.go @@ -2,6 +2,7 @@ package main import ( "flag" + "go_dreamfactory/modules/web" "go_dreamfactory/services" "github.com/liwei1dao/lego" @@ -21,7 +22,8 @@ func main() { ) s.OnInstallComp( //装备组件 ) - lego.Run(s) //运行模块 + lego.Run(s, //运行模块 + web.NewModule()) }