• 依葫芦画瓢理解一个小型Go框架


    最近在开发Go程序,同事( github.com/WiFeng/go-sky )参考go-kit框架封装了一个简易的轮子,包含了Api和Task任务,已经能满足大部分Web需求,依葫芦画瓢,自己理解了下,参考下图:

    1:cmd/service.go

    package main
    
    import (
        "github.com/WiFeng/go-sky"
        "pkg/config"
        "pkg/endpoint"
        "pkg/service"
        "pkg/task"
        "pkg/transport/http"
    )
    
    func main() {
    
        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)
    }

    初始化service、endpoint,NewHandler注册路由作为web服务,再注册Task运行后台任务。

    2:pkg\endpoint\endpoint.go:

    package endpoint
    import "pkg/service"
    
    type Endpoints struct {
        Article ArticleEndpoints
    }
    
    func New(s service.Service) Endpoints {
        return Endpoints{
            Article: NewArticleEndpoints(s),
        }
    }

    返回一个大的Endpoints,其中包含子的Endpoints,会将service.Service结构体传递给Endpoints。

    3:pkg\endpoint\article.go:

    package endpoint
    
    import (
        "context"
        kitendpoint "github.com/go-kit/kit/endpoint"
        . "pkg/entity"
        "pkg/service"
    )
    
    type ArticleEndpoints struct {
        MGet kitendpoint.Endpoint
    }
    
    func NewArticleEndpoints(s service.Service) ArticleEndpoints {
        return ArticleEndpoints{
            MGet: MakeArticleMGetEndpoint(s),
        }
    }
    
    func MakeArticleMGetEndpoint(s service.Service) kitendpoint.Endpoint {
        return func(ctx context.Context, request interface{}) (response interface{}, err error) {
            req := request.(ArticleInfoMGetRequest)
            return s.Article.MGet(ctx, req)
        }
    }

    每一个子的Endpoint应该包含同一种类型的服务,最终调用对应的service服务方法。

    不过ArticleInfoMGetRequest也可以在service\article.go(例子中注册在entity) 中定义。MakeArticleMGetEndpoint返回一个闭包,注册了一个路由。

    4:pkg\entity\article.go

    package entity
    
    type ArticleInfo struct {
        ArticleId int64 `json:"aid"`
        Uid       int64 `json:"uid"`
    }
    
    type ArticleInfoMGetRequest struct {
        BaseRequest
        ArticleIds   []int64 `json:"aids"`
        ForceNoCache bool    `json:"force_no_cache"`
    }
    
    type ArticleInfoMGetRespData struct {
        Infos []ArticleInfo `json:"infos"`
    }
    
    type ArticleInfoMGetResponse struct {
        BaseResponse
        Data ArticleInfoMGetRespData `json:"data"`
    }

    entity包含特定的工具方法。

    5:pkg\service\service.go:

    package service
    
    type Service struct {
        Article ArticleService
    }
    
    func New() Service {
        return Service{
            Article: ArticleService{},
        }
    }

    service大结构体初始化,包括子service初始化。

    6:pkg\service\article.go:

    package service
    
    import (
        "context"
          "pkg/dao"
        . "github.com/xiwujie/article/pkg/entity"
    )
    
    type ArticleSyncJobRequest struct {
        BaseRequest
        Limit   int    `json:"limit"`
        JobName string `json:"job_name"`
    }
    
    type ArticleSyncJobResponse struct {
        BaseResponse
    }
    
    type ArticleService struct {
    }
    
    func (s *ArticleService) MGet(ctx context.Context, req ArticleInfoMGetRequest) (interface{}, error) {
        var resp ArticleInfoMGetResponse
    
        if req.ArticleIds == nil || len(req.ArticleIds) < 1 {
            return resp, nil
        }
        sdao = dao.NewSearchActivityTable(ctx)
        sdao.FetchById()
    
        return resp, nil
    }

    具体的service服务,包含req,response的定义,也可以定义到 entry 目录下。

    7:pkg/dao/article.go

    package dao
    
    import (
        "context"
        "database/sql"
        "fmt"
    
        skydb "github.com/WiFeng/go-sky/database"
    )
    
    const (
        searchActivityTableName = ""
    )
    
    type SearchActivityTable struct {
        db *sql.DB
    }
    
    func NewSearchActivityTable(ctx context.Context) (*SearchActivityTable, error) {
    }
    
    func (t *SearchActivityTable) FetchById(ctx context.Context, id int)  {
    }

    dao方法,主要进行数据库等资源的操作。

    8:pkg\transport\http\handler.go

    func NewHandler(endpoints 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...,
        ))
    
        return r
    }

    注册http路由,endpoint作为参数传递给handler。

     

  • 相关阅读:
    什么是中间件
    从零开始深入了解MySQL的Buffer Pool
    SSH的在线音乐下载网站-JAVA【数据库设计、源码、开题报告】
    2--Linux:基础命令
    12款爆款项目管理工具推荐
    基于JAVA基于Web的社区商超系统的设计与实现计算机毕业设计源码+系统+mysql数据库+lw文档+部署
    三维图形学知识分享--三角剖分网格细分详细代码实现
    快速求解 S[n]=Σ(i=1~n)i^i % 7
    ARM32开发--FreeRTOS-事件组
    Gradle 构建环境变量配置
  • 原文地址:https://blog.csdn.net/m0_73257876/article/details/126758457