当前位置:首页 > 科技  > 软件

用Go实现一个带缓存的REST API服务端

来源: 责编: 时间:2024-01-02 17:27:58 443观看
导读1.REST API原理REST(Representational State Transfer)是一种通过HTTP协议设计API的架构风格,用于构建分布式系统中的网络应用程序。REST API(RESTful API)是基于这种设计风格的应用程序编程接口。其主要优点是其极大的灵

1.REST API原理

REST(Representational State Transfer)是一种通过HTTP协议设计API的架构风格,用于构建分布式系统中的网络应用程序。REST API(RESTful API)是基于这种设计风格的应用程序编程接口。其主要优点是其极大的灵活性, 只要需要直接从服务器向Web应用程序或站点的用户提供数据, 开发人员直接使用REST API即可实现。PuT28资讯网——每日最新资讯28at.com

PuT28资讯网——每日最新资讯28at.com

REST API 的设计目的是创建简单、可伸缩、可维护且具有良好可读性的接口, 以促进客户端和服务器之间的有效通信, 通过使用HTTP协议和一组统一的设计原则, REST API在实现上具备一些特定的属性:PuT28资讯网——每日最新资讯28at.com

  • 资源(Resources):在REST中, 数据或服务都被视为资源。每个资源都有一个唯一的标识符, 用于在网络上标识和定位该资源。
  • 表现层(Representation):资源的状态可以以不同的表现形式呈现, 例如: JSON、XML或HTML。客户端可以通过请求特定的表现形式来与服务器交互。
  • 状态无关(Stateless):REST是状态无关的, 这意味着每个请求从客户端到服务器都包含了足够的信息, 服务器不需要存储客户端的状态。每个请求都应该包含了执行该请求所需的所有信息。
  • 统一接口(Uniform Interface):RESTful API的设计应该遵循一致的接口原则, 使得不同的组件之间的通信变得简单统一。
  • 无状态通信(Stateless Communication):每个请求从客户端到服务器都应该包含足够的信息, 以便服务器能够理解和处理请求,而无需依赖之前的请求。
  • 缓存(Cacheability):REST API支持缓存, 以提高性能和减轻服务器的负担。服务器可以在响应中指定数据的缓存策略,而客户端可以使用缓存来避免重复请求相同的数据。
  • 使用标准方法(Standard Methods):REST使用标准的HTTP方法,如:GET、POST、PUT、DELETE来执行不同的操作, 这些方法对应于对资源的不同操作, 使得API的使用更加直观和符合HTTP标准。

2.REST API服务端设计

下面我将使用Go语言来设计一个REST API的服务端, 这里的模拟场景是通过服务端来对外提供文章的增、删、查服务, 文章的查询方式包括两种: 1.查询服务器所有文章内容。2.根据文章ID查询某篇文章的内容。PuT28资讯网——每日最新资讯28at.com

文章的属性包括三个字段: 文章ID、文章标题、文章内容, 这里可以用一个结构体表示:PuT28资讯网——每日最新资讯28at.com

type Article struct {  ID string `json:"id,omitempty"`  Title string `json:"title,omitempty"`  Content string `json:"content,omitempty"`}

由于我们设计了四个功能接口, 将其转换成接口代码框架如下:PuT28资讯网——每日最新资讯28at.com

// 获取所有文章接口func GetArticles(w http.ResponseWriter, r *http.Request) {     ...}// 获取单篇文章接口func GetArticle(w http.ResponseWriter, r *http.Request) {     ...}// 创建文章接口func CreateArticle(w http.ResponseWriter, r *http.Request) {     ...}// 删除文章接口func DeleteArticle(w http.ResponseWriter, r *http.Request) {     ...}

3.功能代码实现

PuT28资讯网——每日最新资讯28at.com

首先来实现获取所有文章的接口, 具体参考代码如下:PuT28资讯网——每日最新资讯28at.com

// 获取所有文章func GetArticles(w http.ResponseWriter, r *http.Request) {  w.Header().Set("Content-Type", "application/json")  // 尝试从缓存中获取文章列表  if cachedArticles, found := articleCache.Load("all"); found {    json.NewEncoder(w).Encode(cachedArticles)    return  }  // 从原始数据源获取文章列表  json.NewEncoder(w).Encode(Articles)  // 将文章列表存入缓存  articleCache.Store("all", Articles)}

获取所有文章首先是尝试从缓存中获取文章列表, 缓存cachedArticles这里实际是一个sync.Map类型的变量, 支持并发安全, 如果找到的话, 直接序列化成JSON的格式返回。如果缓存中没有找到, 则从原始数据源中获取文章列表(实际应用中应该是从数据库中获取)并序列化成JSON返回。并把该文章列表存入缓存之中。PuT28资讯网——每日最新资讯28at.com

接下来实现第二个接口,通过文章ID来查询, 实现参考代码如下:PuT28资讯网——每日最新资讯28at.com

// 获取单篇文章func GetArticle(w http.ResponseWriter, r *http.Request) {  w.Header().Set("Content-Type", "application/json")  params := mux.Vars(r)  // 尝试从缓存中获取单个文章  if cachedArticle, found := articleCache.Load(params["id"]); found {    json.NewEncoder(w).Encode(cachedArticle)    return  }  // 从原始数据源获取单个文章  for _, article := range Articles {    if article.ID == params["id"] {      json.NewEncoder(w).Encode(article)      // 将单个文章存入缓存      articleCache.Store(params["id"], article)      return    }  }  json.NewEncoder(w).Encode(&Article{})}

首先将传入的ID参数在缓存中进行查找, 找到则直接返回JSON数据。如果没有找到则继续在文章列表中查找, 并将单篇文章存入缓存。PuT28资讯网——每日最新资讯28at.com

创建文章接口参考代码如下:PuT28资讯网——每日最新资讯28at.com

// 创建文章func CreateArticle(w http.ResponseWriter, r *http.Request) {  w.Header().Set("Content-Type", "application/json")  var article Article  _ = json.NewDecoder(r.Body).Decode(&article)  Articles = append(Articles, article)  // 清除所有文章缓存  articleCache.Delete("all")  json.NewEncoder(w).Encode(Articles)}

创建文章列表需要注意的是, 这里为了维护缓存一致性,避免脏数据, 对缓存进行了清空, 以便下次GetArticles()时更新最新的缓存。PuT28资讯网——每日最新资讯28at.com

同理也不难实现删除文章的接口:PuT28资讯网——每日最新资讯28at.com

// 删除文章func DeleteArticle(w http.ResponseWriter, r *http.Request) {  w.Header().Set("Content-Type", "application/json")  params := mux.Vars(r)  // 清除单个文章缓存  articleCache.Delete(params["id"])  for index, article := range Articles {    if article.ID == params["id"] {      Articles = append(Articles[:index], Articles[index+1:]...)      break    }  }  // 清除所有文章缓存  articleCache.Delete("all")  json.NewEncoder(w).Encode(Articles)}

最后, 在main函数中, 我们需要往列表中添加一些数据来模拟服务端保存的文章数, 并且定义四个接口的路由, 整体代码如下:PuT28资讯网——每日最新资讯28at.com

package mainimport (  "encoding/json"  "log"  "net/http"  "sync"  "github.com/gorilla/mux")// Article 结构体表示 API 中的数据模型type Article struct {  ID string `json:"id,omitempty"`  Title string `json:"title,omitempty"`  Content string `json:"content,omitempty"`}// Articles 数组用于存储文章数据var Articles []Articlevar articleCache sync.Map// 获取所有文章func GetArticles(w http.ResponseWriter, r *http.Request) {  w.Header().Set("Content-Type", "application/json")  // 尝试从缓存中获取文章列表  if cachedArticles, found := articleCache.Load("all"); found {    json.NewEncoder(w).Encode(cachedArticles)    return  }  // 从原始数据源获取文章列表  json.NewEncoder(w).Encode(Articles)  // 将文章列表存入缓存  articleCache.Store("all", Articles)}// 获取单个文章func GetArticle(w http.ResponseWriter, r *http.Request) {  w.Header().Set("Content-Type", "application/json")  params := mux.Vars(r)  // 尝试从缓存中获取单个文章  if cachedArticle, found := articleCache.Load(params["id"]); found {    json.NewEncoder(w).Encode(cachedArticle)    return  }  // 从原始数据源获取单个文章  for _, article := range Articles {    if article.ID == params["id"] {      json.NewEncoder(w).Encode(article)      // 将单个文章存入缓存      articleCache.Store(params["id"], article)      return    }  }  json.NewEncoder(w).Encode(&Article{})}// 创建文章func CreateArticle(w http.ResponseWriter, r *http.Request) {  w.Header().Set("Content-Type", "application/json")  var article Article  _ = json.NewDecoder(r.Body).Decode(&article)  Articles = append(Articles, article)  // 清除所有文章缓存  articleCache.Delete("all")  json.NewEncoder(w).Encode(Articles)}// 删除文章func DeleteArticle(w http.ResponseWriter, r *http.Request) {  w.Header().Set("Content-Type", "application/json")  params := mux.Vars(r)  // 清除单个文章缓存  articleCache.Delete(params["id"])  for index, article := range Articles {    if article.ID == params["id"] {      Articles = append(Articles[:index], Articles[index+1:]...)      break    }  }  // 清除所有文章缓存  articleCache.Delete("all")  json.NewEncoder(w).Encode(Articles)}func main() {  // 初始化数据  Articles = append(Articles, Article{ID: "1", Title: "Article 1", Content: "Content 1"})  Articles = append(Articles, Article{ID: "2", Title: "Article 2", Content: "Content 2"})  // 创建路由器  router := mux.NewRouter()  // 定义路由处理程序  router.HandleFunc("/articles", GetArticles).Methods(http.MethodGet)  router.HandleFunc("/articles/{id}", GetArticle).Methods(http.MethodGet)  router.HandleFunc("/articles", CreateArticle).Methods(http.MethodPost)  router.HandleFunc("/articles/{id}", DeleteArticle).Methods(http.MethodDelete)  // 启动服务器  log.Fatal(http.ListenAndServe(":8080", router))}

4.实际运行效果

PuT28资讯网——每日最新资讯28at.com

在本地运行服务端, 服务端将在本地监听8080端口, 通过浏览器输入: http://127.0.0.1:8080/articles, 该接口将获取所有文章,如图:PuT28资讯网——每日最新资讯28at.com

PuT28资讯网——每日最新资讯28at.com

通过API接口通过文章ID查询某一篇文章,接口请求如下:PuT28资讯网——每日最新资讯28at.com

PuT28资讯网——每日最新资讯28at.com

新增一条新文章是POST请求, 这里主要通过Apifox发送POST请求,如图:PuT28资讯网——每日最新资讯28at.com

PuT28资讯网——每日最新资讯28at.com

从返回的结果来看, 成功添加了一条新记录, 再次使用获取全部文章接口看一下,如图:PuT28资讯网——每日最新资讯28at.com

PuT28资讯网——每日最新资讯28at.com

新记录确实添加成功。PuT28资讯网——每日最新资讯28at.com

最后, 还是通过Apifox,我们发送一个删除ID为2的文章请求,如图:PuT28资讯网——每日最新资讯28at.com

PuT28资讯网——每日最新资讯28at.com

从Apifox返回的结果来看,确实删除成功了,  现在再获取一下全部文章,如图:PuT28资讯网——每日最新资讯28at.com

PuT28资讯网——每日最新资讯28at.com

所有接口全部验证成功。PuT28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-56402-0.html用Go实现一个带缓存的REST API服务端

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 六种不同类型的K8s部署策略总结

下一篇: 聊一聊 C# 的线程本地存储TLS到底是什么

标签:
  • 热门焦点
  • Redmi Buds 4开箱简评:才199还有降噪 可以无脑入

    在上个月举办的Redmi Note11T Pro系列新机发布会上,除了两款手机新品之外,Redmi还带来了两款TWS真无线蓝牙耳机产品,Redmi Buds 4和Redmi Buds 4 Pro,此前我们在Redmi Note11T
  • 5月iOS设备性能榜:M1 M2依旧是榜单前五

    和上个月一样,没有新品发布的iOS设备性能榜的上榜设备并没有什么更替,仅仅只有跑分变化而产生的排名变动,刚刚开始的苹果WWDC2023,推出的产品也依旧是新款Mac Pro、新款Mac Stu
  • JavaScript 混淆及反混淆代码工具

    介绍在我们开始学习反混淆之前,我们首先要了解一下代码混淆。如果不了解代码是如何混淆的,我们可能无法成功对代码进行反混淆,尤其是使用自定义混淆器对其进行混淆时。什么是混
  • 一篇聊聊Go错误封装机制

    %w 是用于错误包装(Error Wrapping)的格式化动词。它是用于 fmt.Errorf 和 fmt.Sprintf 函数中的一个特殊格式化动词,用于将一个错误(或其他可打印的值)包装在一个新的错误中。使
  • Java NIO内存映射文件:提高文件读写效率的优秀实践!

    Java的NIO库提供了内存映射文件的支持,它可以将文件映射到内存中,从而可以更快地读取和写入文件数据。本文将对Java内存映射文件进行详细的介绍和演示。内存映射文件概述内存
  • 一篇文章带你了解 CSS 属性选择器

    属性选择器对带有指定属性的 HTML 元素设置样式。可以为拥有指定属性的 HTML 元素设置样式,而不仅限于 class 和 id 属性。一、了解属性选择器CSS属性选择器提供了一种简单而
  • 2天涨粉255万,又一赛道在抖音爆火

    来源:运营研究社作者 | 张知白编辑 | 杨佩汶设计 | 晏谈梦洁这个暑期,旅游赛道彻底火了:有的「地方」火了——贵州村超旅游收入 1 个月超过 12 亿;有的「博主」火了&m
  • 三星Galaxy Z Fold5官方渲染图曝光:13.4mm折叠厚度依旧感人

    据官方此前宣布,三星将于7月26日在韩国首尔举办Unpacked活动,届时将带来带来包括Galaxy Buds 3、Galaxy Watch 6、Galaxy Tab S9、Galaxy Z Flip 5、
  • 支持aptX Lossless无损传输 iQOO TWS 1赛道版发布限时优惠价369元

    2023年7月4日,“无损音质,声动人心”iQOO TWS 1正式发布,支持aptX Lossless无损传输,限时优惠价369元。iQOO TWS 1耳机率先支持端到端aptX Lossless无
Top