Eswlnk Blog Eswlnk Blog
  • 资源
    • 精彩视频
    • 破解专区
      • WHMCS
      • WordPress主题
      • WordPress插件
    • 其他分享
    • 极惠VPS
    • PDF资源
  • 关于我
    • 论文阅读
    • 关于本站
    • 通知
    • 左邻右舍
    • 玩物志趣
    • 日志
    • 专题
  • 热议话题
    • 游戏资讯
  • 红黑
    • 渗透分析
    • 攻防对抗
    • 代码发布
  • 自主研发
    • 知识库
    • 插件
      • ToolBox
      • HotSpot AI 热点创作
    • 区块
    • 快乐屋
    • 卡密
  • 乱步
    • 文章榜单
    • 热门标签
  • 问答中心反馈
  • 注册
  • 登录
首页 › 代码发布 › 如何利用GO中的泛型实现客户端分页API

如何利用GO中的泛型实现客户端分页API

Eswlnk的头像
Eswlnk
2022-05-19 22:41:18
如何利用GO中的泛型实现客户端分页API-Eswlnk Blog
智能摘要 AI
本文介绍了Go语言1.18版本中泛型在RESTful API客户端中的应用。通过定义泛型类型`Pager[T any]`,实现了分页资源的迭代处理,支持向前和向后翻页,并提供了`PageInfo`获取页面元数据的功能。此外,还展示了如何使用泛型接口`pageIterator[T any]`创建`PageScanner[T any]`,简化了遍历分页资源的过程,使用户能够方便地逐项处理资源。这种方法不仅提高了代码的可重用性和类型安全性,还使得API客户端能够灵活处理不同类型的资源。

最近看到一篇有关GO的泛型使用,对比最近使用Java编写的后端,感觉还是有点差别,毕竟是个人的感受。以前博客也有一篇有关go的文章,有兴趣的可以浏览《详解泛型是如何让你的GO代码变慢》。

如何利用GO中的泛型实现客户端分页API-Eswlnk Blog

功能假设

假设我们有一个用于总账的 RESTful API,带有端点,它返回一个分页的资源集合:

  1. GET /accounts,检索帐户列表,按一些查询参数过滤和排序;
  2. GET /accounts/:uuid/transactions,检索帐户的交易列表;
  3. GET /postings,检索存储在分类帐中的过帐列表。

实际结构和响应体是实现细节,在这里并不重要。

功能实现

在 Go 1.18 中,我们可以将此 API 的客户端方法指定为相应的List*方法,返回泛型类型Pager[T any]:

type LedgerAPIClient struct {
    // unexported fields
}

func (c *LedgerAPIClient) ListAccounts(context.Context, ListAccountsInput) *Pager[Account] { ··· }

func (c *LedgerAPIClient) ListAccountTransactions(context.Context, ListAccountTransactionsInput) *Pager[Transaction] { ··· }

func (c *LedgerAPIClient) ListPostings(context.Context, ListPostingsInput) *Pager[Posting] { ··· }

泛型类型的 APIPager[T any]如下所示:

// PagerDone is a sentinel error, which pager's NextPage and PrevPage methods return,
// when there aren't any more pages to iterate over.
var PagerDone = errors.New("no more pages to iterate")

type Pager[T any] struct {
    // unexported fields
}

// NextPage retrieves the next page in the collection of T.
// It returns PagerDone error after it reaches the last page.
func (p *Pager[T]) NextPage() ([]T, error) { ··· }

// PrevPage retrieves the previous page in the collection of T.
// It returns PagerDone error after it reaches the first page.
func (p *Pager[T]) PrevPage() ([]T, error) { ··· }

type PageInfo struct {
    Token   string
    HasNext bool
    HasPrev bool
}

// PageInfo returns a metadata about the current page.
func (p *Pager[T]) PageInfo() PageInfo { ··· }

在底层,该Pager[T]类型实现了一个迭代器,它将状态与当前页面保持一致,并通过对其 API 客户端的反向引用调用 API 端点,以检索具有下一页或上一页的列表。实际实现可能如本示例 gist所示。

如何利用GO中的泛型实现客户端分页API-Eswlnk Blog

为了遍历资源的集合,我们的用户LedgerAPIClient调用List*相关API资源的方法,遍历返回的pager,直到后者用完,或者用户对手头的结果满意:

c := api.NewLedgerAPIClient()

pager := c.ListAccounts(ctx, input)
for {
    accs, err := pager.NextPage()
    if errors.Is(err, api.PagerDone) {
        break
    }
    if err != nil { ··· }

    for _, acc := range accs {
        // do something with this page's list of accounts
    }
}

比方说,对于某个用例,使用集合更方便,就好像它不是一个分页的资源列表,而是一个连续的个人资源流。

如何利用GO中的泛型实现客户端分页API-Eswlnk Blog

这个实现的好处是泛型类型Pager[T]实现了一个泛型接口:

type pageIterator[T any] interface {
    NextPage() ([]T, error)
}

我们可以实现一个帮助器,它接受一个pageIterator[T any]接口,并使用它的NextPage()方法,帮助器扫描整个集合,一个一个地返回它的项目。泛型允许实现这个助手一次,它可以在我们的 API 客户端中使用任何类型的资源,并为用户提供一个强类型的 API 来使用:

type PageScanner[T any] struct {
    Pager pageIterator[T]
    // a buffer of items yet to be conumed by the user
    list [T]
}

// Next returns next item from the underlying pager.
// After all items of the current page are consumed, PageScanner moves to the next page.
func (s *PageScanner[T any]) Next() (item T, err error) {
    for len(s.list) == 0 {
        s.list, err = s.Pager.NextPage()
        if err != nil {
            return item, err
        }
    }

    item = s.list[0]
    s.list = s.list[1:]

    return item, nil
}

这就是用户将其应用于他们的代码的方式:

c := api.NewLedgerAPIClient()

pager := c.ListAccountTransactions(ctx, input)

// (caveat) it seems that, in Go 1.18 the compiler can't figure out the underlying type
// of the pager's list, so we have to specify the type explicitely, when create PageScanner[T]
scanner := &api.PageScaner[Transaction]{
    Pager: pager,
}
for {
    trx, err := scanner.Next()
    if errors.Is(err, api.PagerDone) {
        break
    }
    if err != nil { ··· }

    // do something with an individual transaction
}
本站默认网盘访问密码:1166
本站默认网盘访问密码:1166
APIGOGO代码go语言分页泛型
0
0
Eswlnk的头像
Eswlnk
一个有点倒霉的研究牲站长
赞赏
通用网盘下载链接检测_Serverless云函数应用
上一篇
巧妙应用Docker运行HuggingFace
下一篇

评论 (0)

请登录以参与评论
现在登录
    发表评论

猜你喜欢

  • 「日志记录」逆向必应翻译网页版API实现免费调用
  • 「代码分享」第三方平台VIP视频解析API接口
  • 「至臻原创」某系统网站登录功能监测
  • 「技术教程」使用Playwright进行API接口测试
  • 「开发日志」在Vue3中如何为路由Query参数标注类型
Eswlnk的头像

Eswlnk

一个有点倒霉的研究牲站长
1108
文章
319
评论
679
获赞

随便看看

「代码发布」CSS3实现波纹扩散旋转的动画特效
2022-08-14 16:55:59
「API」Google Address Validation API 普遍可用以提高地址准确性
2023-01-21 20:23:52
WordPress开发日志:二次修改WP七牛云存储插件适应GIF
2021-11-24 23:31:46

文章目录

专题展示

WordPress53

工程实践37

热门标签

360 AI API CDN java linux Nginx PDF PHP python SEO Windows WordPress 云服务器 云服务器知识 代码 免费 安全 安卓 工具 开发日志 微信 微软 手机 插件 攻防 攻防对抗 教程 日志 渗透分析 源码 漏洞 电脑 破解 系统 编程 网站优化 网络 网络安全 脚本 苹果 谷歌 软件 运维 逆向
  • 首页
  • 知识库
  • 地图
Copyright © 2023-2025 Eswlnk Blog. Designed by XiaoWu.
本站CDN由 壹盾安全 提供高防CDN安全防护服务
蜀ICP备20002650号-10
页面生成用时 0.808 秒   |  SQL查询 41 次
本站勉强运行:
友情链接: Eswlnk Blog 网站渗透 倦意博客 特资啦!个人资源分享站 祭夜博客 iBAAO壹宝头条
  • WordPress142
  • 网络安全64
  • 漏洞52
  • 软件52
  • 安全48
现在登录
  • 资源
    • 精彩视频
    • 破解专区
      • WHMCS
      • WordPress主题
      • WordPress插件
    • 其他分享
    • 极惠VPS
    • PDF资源
  • 关于我
    • 论文阅读
    • 关于本站
    • 通知
    • 左邻右舍
    • 玩物志趣
    • 日志
    • 专题
  • 热议话题
    • 游戏资讯
  • 红黑
    • 渗透分析
    • 攻防对抗
    • 代码发布
  • 自主研发
    • 知识库
    • 插件
      • ToolBox
      • HotSpot AI 热点创作
    • 区块
    • 快乐屋
    • 卡密
  • 乱步
    • 文章榜单
    • 热门标签
  • 问答中心反馈