Go打造REST Server【二】:用路由的三方库来实现

前言

在之前的文章中,我们用Go的标准库来实现了服务器,JSON渲染重构为辅助函数,使特定的路由处理程序相当简洁。
我们剩下的问题是路径路由逻辑,这是所有编写无依赖HTTP服务器的人都会遇到的问题,除非服务器只处理一到两个路由,否则组织路由器代码是冗长和困难的。

高级路由

首先的想法是抽象路由,可能使用一组函数或带有方法的数据类型,有许多有趣的临时方法可以做到这一点,Go生态系统中有许多功能强大且使用良好的三方路由包可以为做这件事。
我们再回顾一下设计的服务器路由:

POST   /page/              :  create a page, returns ID
GET    /page/<pageid>      :  returns a single page by ID
GET    /page/              :  returns all pages
DELETE /page/<pageid>      :  delete a page by ID
PUT    /page/<pageid>      :  update a page by ID
GET    /tag/<tagname>      :  returns list of pages with this tag
GET    /due/<yy>/<mm>/<dd> :  returns list of pages due by this date

我们可以做几件事来使路由更符合观感:

  • 添加一种方法来为同一路由上的不同方法设置单独的处理程序。例如,/page/的POST应该转到一个处理程序,GET /page/到另一个处理程序,等等。
  • 添加一种“更深”匹配的方法;例如,我们应该可以说/page/进入一个处理程序,而 /page/使用数字ID进入另一个处理程序。
  • 当我们这样做时,匹配器应该只从/page/中提取数字ID并以某种方便的方式将其传递给处理程序。

由于HTTP处理程序的可组合性,在Go中编写自定义路由器非常简单,例如最流行的第三方方路由包之一:gorilla/mux。

gorilla/mux实现的服务器

gorilla/mux是最久的流行Go HTTP路由器之一,根据文档,名称mux代表“HTTP请求多路复用器”(与标准库中的含义相同)。
因为它是一个目标明确的包,所以它的使用相当简单,以下是路由的定义方式:

router := mux.NewRouter()
router.StrictSlash(true)
server := NewPageServer()router.HandleFunc("/page/", server.createPageHandler).Methods("POST")
router.HandleFunc("/page/", server.getAllPagesHandler).Methods("GET")
router.HandleFunc("/page/", server.deleteAllPagesHandler).Methods("DELETE")
router.HandleFunc("/page/", server.updatePageHandler).Methods("PUT")
router.HandleFunc("/page/{id:[0-9]+}/", server.getPageHandler).Methods("GET")
router.HandleFunc("/page/{id:[0-9]+}/", server.deletePageHandler).Methods("DELETE")
router.HandleFunc("/tag/", server.tagHandler).Methods("GET")
router.HandleFunc("/due/", server.dueHandler).Methods("GET")

通过将方法调用附加到路由上,我们可以轻松地将同一路径上的不同方法定向到不同的处理程序。路径中的模式匹配(使用正则表达式语法)让我们可以轻松地区分顶级路由定义中的/page/和/page/。

我们来看看getPageHandler:

func (p *PageServer) getPageHandler(w http.ResponseWriter, r *http.Request) {log.Printf("handling get page at %s\n", r.URL.Path)// Here and elsewhere, not checking error of Atoi because the router only// matches the [0-9]+ regex.id, _ := strconv.Atoi(mux.Vars(r)["id"])ret, err := p.store.GetPage(id)if err != nil {http.Error(w, err.Error(), http.StatusNotFound)return}renderJSON(w, ret)
}

在路由定义中,路由/page/{id:[0-9]+}/定义了解析路径的正则表达式,但也将标识符部分分配给“id”。这个“变量”可以通过在请求上调用mux.Vars来访问。

方法对比

为了理解GET /page/路由在我们的原始服务器中是如何处理的,必须采用以下代码阅读路径:
在这里插入图片描述
而这是使用gorilla/mux时的路径:
在这里插入图片描述
除了可以跳过的步骤更少之外,要阅读的代码也大大减少了,从代码可读性的角度来看,使用gorilla/mux的路径定义简短明了,阅读者很清楚这是如何工作的。另一个优势是,我们现在可以在一个地方一目了然地轻松查看所有路由。事实上,路由配置代码现在看起来与我们非正式的REST API定义非常相似。
像gorilla/mux这样的包,因为它们是一个精密工具,他们只做一件事,而且做得很好,而且他们不会“感染”整个程序,使他们以后难以删除或替换。如果我们检查这部分的服务器代码,我们会注意到使用gorilla/mux的部分仅限于相对较少的代码行。如果我们在项目生命周期的后期发现这个包有一个致命的限制,用另一个路由包(或手动版本)替换它应该是相当简单的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/577314.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【八股】泛型

泛型存在的意义&#xff1f; 为了使相同的代码适用于多种数据类型&#xff0c;也就是代码复用。 参数类型上下限限制 <?> 无限制 <? extends E> 声明了类型的上界&#xff0c;表示参数类型可以是他或他的子类。 <? super E> 声明了类型的下界&#xf…

STM32之HAL开发——串口配置(源码)

串口收发原理框图&#xff08;F1系列&#xff09; 注意&#xff1a;数据寄存器有俩个一个是收一个是发&#xff0c;但是在标准库或者HAL库中没有特别区分开来是俩个寄存器&#xff01; USART 初始化结构体详解 HAL 库函数对每个外设都建立了一个初始化结构体&#xff0c;比如 …

2024年妈妈杯数学建模思路B题思路分享

文章目录 1 赛题思路2 比赛日期和时间3 组织机构4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…

ethers.js:sign(签名)

Signers 在ethers中Signer是以太坊账户的抽象&#xff0c;可以用来签名消息和交易&#xff0c;如将签名的交易发送到以太坊网络以执行状态更改的操作。 npm install ethers5.4.0// 引入 import { ethers } from ethers签名 this.provider new ethers.providers.Web3Provider(…

Docker安装xxl-job并整合到SpringBoot项目

1. 创建数据库 执行如下SQL语句创建相关表 CREATE database if NOT EXISTS xxl_job default character set utf8mb4 collate utf8mb4_general_ci; use xxl_job;SET NAMES utf8mb4; CREATE TABLE xxl_job_info (id int(11) NOT NULL AUTO_INCREMENT,job_group int(11) NOT NUL…

基于java+springcloud的分布式架构网上商城

开发语言&#xff1a;Java 框架&#xff1a;springcloud JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Mave…

Python 垃圾回收和弱引用(Weakref)

Python中的赋值语句是建立变量名与对象的引用关系&#xff0c;多个变量可以引用同一个对象&#xff0c;当对象的引用数归零时&#xff0c;可能会被当作垃圾回收。而弱引用即可以引用对象&#xff0c;又不会阻止对象被当作垃圾回收&#xff0c;因此这个特性非常适合用在缓存场景…

报错 /core/library/think/cache/driver/File.php 第 126 行左右(已解决)

报错 /core/library/think/cache/driver/File.php 第 126 行左右 解决方法&#xff1a; 网站后台版本低于v1.5.2出现的缓存问题&#xff0c;如果无法登录后台了&#xff0c;就通过FTP&#xff0c;把 /data/runtime 里的都删掉&#xff0c;然后进后台升级到最新版 一、进入宝…

vmWare虚拟机下载安装详细教程,手把手一步一步教学

一.下载 先去官网下载vm 官网地址:https://www.vmware.com/ 官网下载速度太慢了 国内应用商店或者别的下载地址:vmware下载_vmware下载免费中文版客户端[虚拟机]-下载之家 然后再去下载一个镜像 地址是:Index of /centos/7/isos/x86_64/ 我个人下载的是这个 ,看各位的需求…

【Java】ArrayList数组的扩容机制 jdk1.8

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 ArrayList和普通数组不同&#xff0c;ArrayList支持动态扩容&#xff0c;那么ArrayList到底是如何扩容的呢&#xff1f;你又是否知道ArrayList数组的初始长度是多少呢&#xff1f; 在开始介绍之前&#xff0c;我们要先介…

代码随想录阅读笔记-二叉树【翻转二叉树】

题目 翻转一棵二叉树。 思路 如果要从整个树来看&#xff0c;翻转还真的挺复杂&#xff0c;整个树以中间分割线进行翻转&#xff0c;如图&#xff1a; 可以发现想要翻转它&#xff0c;其实就把每一个节点的左右孩子交换一下就可以了。 关键在于遍历顺序&#xff0c;前中后序应…

2024年妈妈杯数学建模思路A题B题C题D题思路分享

文章目录 1 赛题思路2 比赛日期和时间3 组织机构4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…