当前位置: 首页 > 科技观察

我根据葫芦画图理解了一个Go小框架

时间:2023-03-16 14:23:12 科技观察

最近在开发一个围棋程序。我的同事(github.com/WiFeng/go-sky)参考了go-kit框架,封装了一个简单的轮子,包括Api和Task任务。可以满足大部分的web需求,照葫芦画瓢,自己理解,参考下图:1:cmd/service.gopackagemainimport("github.com/WiFeng/go-sky""pkg/config""pkg/endpoint""pkg/service""pkg/task""pkg/transport/http")funcmain(){var(service=service.New()endpoints=endpoint.New(service)httpHandler=http.NewHandler(endpoints))sky.LoadAppConfig(&config.GlobalAppConfig)sky.RegisterTask(task.Start,nil,true)sky.Run(httpHandler)}初始化服务和端点,NewHandler将路由注册为web服务,然后注册Task运行后台任务.2:pkg\endpoint\endpoint.go:packageendpointimport"pkg/service"typeEndpointsstruct{ArticleArticleEndpoints}funcNew(sservice.Service)Endpoints{returnEndpoints{Article:NewArticleEndpoints(s),}}返回一个大端点,其中包含子Endpoints,会将service.Service结构传递给Endpoints。3:pkg\endpoint\article.go:packageendpointimport("context"kitendpoint"github.com/go-kit/kit/endpoint"."pkg/entity""pkg/service")typeArticleEndpoints结构{MGetkitendpoint.Endpoint}funcNewArticleEndpoints(sservice.Service)ArticleEndpoints{returnArticleEndpoints{MGet:MakeArticleMGetEndpoint(s),}}funcMakeArticleMGetEndpoint(sservice.Service)kitendpoint.Endpoint{returnfunc(ctxcontext.Context,请求接口{})(响应interface{},errerror){req:=request.(ArticleInfoMGetRequest)returns.Article.MGet(ctx,req)}}每个子Endpoint应该包含相同类型的服务,最后调用相应的服务方法。但是ArticleInfoMGetRequest也可以定义在service\article.go中(示例中注册在entity中)。MakeArticleMGetEndpoint返回一个注册路由的闭包。4:pkg\entity\article.gopackage实体类型ArticleInfostruct{ArticleIdint64`json:"aid"`Uidint64`json:"uid"`}typeArticleInfoMGetRequeststruct{BaseRequestArticleIds[]int64`json:"aids"`ForceNoCachebool`json:"force_no_cache"`}typeArticleInfoMGetRespDatastruct{Infos[]ArticleInfo`json:"infos"`}typeArticleInfoMGetResponsestruct{BaseResponseDataArticleInfoMGetRespData`json:"data"`}实体包含特定的工具方法。5:pkg\service\service.go:packageservicetypeServicestruct{ArticleService}funcNew()Service{returnService{Article:ArticleService{},}}服务大结构初始化,包括子服务初始化。6:pkg\service\article.go:packageserviceimport("context""pkg/dao"."github.com/xiwujie/article/pkg/entity")typeArticleSyncJobRequeststruct{BaseRequestLimitint`json:"limit"`JobName字符串`json:"job_name"`}typeArticleSyncJobResponsestruct{BaseResponse}typeArticleServicestruct{}func(s*ArticleService)MGet(ctxcontext.Context,reqArticleInfoMGetRequest)(interface{},error){varrespArticleInfoMGetResponseifreq.ArticleIds==无||len(req.ArticleIds)<1{returnresp,nil}sdao=dao.NewSearchActivityTable(ctx)sdao.FetchById()returnresp,nil}具体service服务,包括req和response的定义,也可以定义在入口目录。7:pkg/dao/article.gopackagedaoimport("context""database/sql""fmt"skydb"github.com/WiFeng/go-sky/database")const(searchActivityTableName="")typeSearchActivityTablestruct{db*sql.DB}funcNewSearchActivityTable(ctxcontext.Context)(*SearchActivityTable,error){}func(t*SearchActivityTable)FetchById(ctxcontext.Context,idint){}dao方法,主要是对数据库等资源的操作。8:pkg\transport\http\handler.gofuncNewHandler(端点endpoint.Endpoints)http.Handler{r:=skyhttp.NewRouter()genericOptions:=[]kithttp.ServerOption{kithttp.ServerErrorEncoder(genericErrorEncoder),}r.Methods(http.MethodPost).Path(ArticleInfoMgetURI).Handler(skyhttp.NewServer(endpoints.Article.MGet,decodeHTTPArticleInfoMgetRequest,encodeHTTPGenericResponse,genericOptions...,))returnr}注册http路由,endpoint传递给handler作为参数。