实现性能

继上一节,咱们实现了根本的web服务。
本节咱们依据语雀凋谢文档 https://www.yuque.com/yuque/developer/api,
新增以下性能

  • 语雀文章详情
  • 语雀列表
  • 语雀搜寻

代码实现

本节残缺代码,参考:https://github.com/golangtips...

减少 servcie 层,并创立以下文件

  • service/intf/yuque.go 接口定义
  • service/internal/yuque.go 具体外部实现
  • service/set.go 服务汇合
  1. 定义接口 service/intf/yuque.go

    package intfimport ( "context" "time")type IYuQue interface { // GetRepoDocList 获取一个仓库的文档列表 //  文档 https://www.yuque.com/yuque/developer/doc GetRepoDocList(ctx context.Context, request *GetRepoDocListRequest) (*GetRepoDocListResponse, error) // GetRepoDocDetail 获取单篇文档的详细信息 //  文档 https://www.yuque.com/yuque/developer/doc GetRepoDocDetail(ctx context.Context, request *GetRepoDocDetailRequest) (*GetRepoDocDetailResponse, error) // Search 搜寻 //  文档 https://www.yuque.com/yuque/developer/high_level_api Search(ctx context.Context, request *SearchRequest) (*SearchResponse, error)}// GetRepoDocListRequest 获取一个仓库的文档列表type GetRepoDocListRequest struct { Namespace          string // Offset             int    // Limit              int    // OptionalProperties int    // 获取文档浏览数}// GetRepoDocListResponse 获取一个仓库的文档列表type GetRepoDocListResponse struct { Data []Doc `json:"data"`}// GetRepoDocDetailRequest 获取单篇文档的详细信息type GetRepoDocDetailRequest struct { Namespace string Slug      string Raw       int // raw=1 返回文档最原始的格局}// GetRepoDocDetailResponse 获取单篇文档的详细信息type GetRepoDocDetailResponse struct { Abilities struct {     Update  bool `json:"update"`     Destroy bool `json:"destroy"` } `json:"abilities"` Data DocDetail `json:"data"`}// SearchRequest 搜寻申请type SearchRequest struct { Type    string // 资源类型 Offset  int    // 分页,1、2... Scope   int    // 搜寻门路 Related bool   // 搜寻与我相干的传递 true}// SearchResponse 搜寻后果type SearchResponse struct { // ...}// Doc 文档根本信息,个别用在列表场景// https://www.yuque.com/yuque/developer/docserializertype Doc struct { CreatedAt string `json:"created_at"` ID        int64  `json:"id"` Public    int64  `json:"public"` Slug      string `json:"slug"` Status    int64  `json:"status"` Title     string `json:"title"` UpdatedAt string `json:"updated_at"`}// DocDetail 文档详细信息// https://www.yuque.com/yuque/developer/docdetailserializertype DocDetail struct { Id     int    `json:"id"` Slug   string `json:"slug"` Title  string `json:"title"` BookId int    `json:"book_id"` Book   struct {     Id               int       `json:"id"`     Type             string    `json:"type"`     Slug             string    `json:"slug"`     Name             string    `json:"name"`     UserId           int       `json:"user_id"`     Description      string    `json:"description"`     CreatorId        int       `json:"creator_id"`     Public           int       `json:"public"`     ItemsCount       int       `json:"items_count"`     LikesCount       int       `json:"likes_count"`     WatchesCount     int       `json:"watches_count"`     ContentUpdatedAt time.Time `json:"content_updated_at"`     UpdatedAt        time.Time `json:"updated_at"`     CreatedAt        time.Time `json:"created_at"`     Namespace        string    `json:"namespace"`     User             struct {         Id               int         `json:"id"`         Type             string      `json:"type"`         Login            string      `json:"login"`         Name             string      `json:"name"`         Description      interface{} `json:"description"`         AvatarUrl        string      `json:"avatar_url"`         BooksCount       int         `json:"books_count"`         PublicBooksCount int         `json:"public_books_count"`         FollowersCount   int         `json:"followers_count"`         FollowingCount   int         `json:"following_count"`         CreatedAt        time.Time   `json:"created_at"`         UpdatedAt        time.Time   `json:"updated_at"`         Serializer       string      `json:"_serializer"`     } `json:"user"`     Serializer string `json:"_serializer"` } `json:"book"` UserId  int `json:"user_id"` Creator struct {     Id               int         `json:"id"`     Type             string      `json:"type"`     Login            string      `json:"login"`     Name             string      `json:"name"`     Description      interface{} `json:"description"`     AvatarUrl        string      `json:"avatar_url"`     BooksCount       int         `json:"books_count"`     PublicBooksCount int         `json:"public_books_count"`     FollowersCount   int         `json:"followers_count"`     FollowingCount   int         `json:"following_count"`     CreatedAt        time.Time   `json:"created_at"`     UpdatedAt        time.Time   `json:"updated_at"`     Serializer       string      `json:"_serializer"` } `json:"creator"` Format            string      `json:"format"` Body              string      `json:"body"` BodyDraft         string      `json:"body_draft"` BodyHtml          string      `json:"body_html"` BodyLake          string      `json:"body_lake"` BodyDraftLake     string      `json:"body_draft_lake"` Public            int         `json:"public"` Status            int         `json:"status"` ViewStatus        int         `json:"view_status"` ReadStatus        int         `json:"read_status"` LikesCount        int         `json:"likes_count"` CommentsCount     int         `json:"comments_count"` ContentUpdatedAt  time.Time   `json:"content_updated_at"` DeletedAt         interface{} `json:"deleted_at"` CreatedAt         time.Time   `json:"created_at"` UpdatedAt         time.Time   `json:"updated_at"` PublishedAt       time.Time   `json:"published_at"` FirstPublishedAt  time.Time   `json:"first_published_at"` WordCount         int         `json:"word_count"` Cover             interface{} `json:"cover"` Description       string      `json:"description"` CustomDescription interface{} `json:"custom_description"` Hits              int         `json:"hits"` Serializer        string      `json:"_serializer"`}
  2. 接口实现 service/intf/yuque.go

    package internalimport ( "context" "encoding/json" "fmt" "io" "log" "net/http" "strconv" "time" "github.com/golangtips/yuque/service/intf")var _ intf.IYuQue = (*YuQue)(nil)type YuQue struct { UserAgent string //利用名称 baseURL   string token     string client    *http.Client}func NewYuQue(baseURL, token, userAgent string) *YuQue { client := &http.Client{     Timeout: 10 * time.Second, } return &YuQue{     UserAgent: userAgent,     baseURL:   baseURL,     token:     token,     client:    client, }}func (y *YuQue) GetRepoDocList(ctx context.Context, request *intf.GetRepoDocListRequest) (*intf.GetRepoDocListResponse, error) { url := fmt.Sprintf("%s/repos/%s/docs", y.baseURL, request.Namespace) req := y.buildHTTPRequest("GET", url, nil) q := req.URL.Query() if request.Offset > 0 {     q.Add("offset", strconv.Itoa(request.Offset)) } if request.Limit > 0 {     q.Add("limit", strconv.Itoa(request.Limit)) } req.URL.RawQuery = q.Encode() resp, err := y.client.Do(req) if err != nil {     return nil, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil {     return nil, fmt.Errorf("ioutil: %w", err) } var response intf.GetRepoDocListResponse if err = json.Unmarshal(body, &response); err != nil {     return nil, err } return &response, nil}func (y *YuQue) GetRepoDocDetail(_ context.Context, request *intf.GetRepoDocDetailRequest) (*intf.GetRepoDocDetailResponse, error) { url := fmt.Sprintf("%s/repos/%s/docs/%s", y.baseURL, request.Namespace, request.Slug) req := y.buildHTTPRequest("GET", url, nil) resp, err := y.client.Do(req) if err != nil {     return nil, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil {     return nil, fmt.Errorf("ioutil: %w", err) } log.Println(string(body)) var detail intf.GetRepoDocDetailResponse if err = json.Unmarshal(body, &detail); err != nil {     return nil, err } return &detail, nil}func (y *YuQue) Search(ctx context.Context, request *intf.SearchRequest) (*intf.SearchResponse, error) { return &intf.SearchResponse{     // }, nil}// buildHTTPRequest 辅助函数func (y *YuQue) buildHTTPRequest(method, url string, body io.Reader) *http.Request { req, _ := http.NewRequest(method, url, body) req.Header.Add("User-Agent", y.UserAgent) req.Header.Add("X-Auth-Token", y.token) return req}
  3. 增加到服务汇合 service/set.go

    package serviceimport ( "github.com/golangtips/yuque/config" "github.com/golangtips/yuque/service/internal" "github.com/golangtips/yuque/service/intf")type Set struct { YuQue intf.IYuQue}func NewSet(toml *config.Toml) (*Set, error) { var yueque intf.IYuQue {     c := toml.YuQue     yueque = internal.NewYuQue(c.BaseURL, c.Token, c.UserAgent) } return &Set{     YuQue: yueque, }, nil}