REST(Representational State Transfer)是一种通过HTTP协议设计API的架构风格,用于构建分布式系统中的网络应用程序。REST API(RESTful API)是基于这种设计风格的应用程序编程接口。其主要优点是其极大的灵活性, 只要需要直接从服务器向Web应用程序或站点的用户提供数据, 开发人员直接使用REST API即可实现。
创新互联建站是一家专注于网站建设、做网站与策划设计,平阴网站建设哪家好?创新互联建站做网站,专注于网站建设十载,网设计领域的专业建站公司;建站业务涵盖:平阴等地区。平阴做网站价格咨询:13518219792
REST API 的设计目的是创建简单、可伸缩、可维护且具有良好可读性的接口, 以促进客户端和服务器之间的有效通信, 通过使用HTTP协议和一组统一的设计原则, REST API在实现上具备一些特定的属性:
下面我将使用Go语言来设计一个REST API的服务端, 这里的模拟场景是通过服务端来对外提供文章的增、删、查服务, 文章的查询方式包括两种: 1.查询服务器所有文章内容。2.根据文章ID查询某篇文章的内容。
文章的属性包括三个字段: 文章ID、文章标题、文章内容, 这里可以用一个结构体表示:
type Article struct {
ID string `json:"id,omitempty"`
Title string `json:"title,omitempty"`
Content string `json:"content,omitempty"`
}
由于我们设计了四个功能接口, 将其转换成接口代码框架如下:
// 获取所有文章接口
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) {
...
}
首先来实现获取所有文章的接口, 具体参考代码如下:
// 获取所有文章
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返回。并把该文章列表存入缓存之中。
接下来实现第二个接口,通过文章ID来查询, 实现参考代码如下:
// 获取单篇文章
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数据。如果没有找到则继续在文章列表中查找, 并将单篇文章存入缓存。
创建文章接口参考代码如下:
// 创建文章
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()时更新最新的缓存。
同理也不难实现删除文章的接口:
// 删除文章
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函数中, 我们需要往列表中添加一些数据来模拟服务端保存的文章数, 并且定义四个接口的路由, 整体代码如下:
package main
import (
"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 []Article
var 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))
}
在本地运行服务端, 服务端将在本地监听8080端口, 通过浏览器输入: http://127.0.0.1:8080/articles, 该接口将获取所有文章,如图:
通过API接口通过文章ID查询某一篇文章,接口请求如下:
新增一条新文章是POST请求, 这里主要通过Apifox发送POST请求,如图:
从返回的结果来看, 成功添加了一条新记录, 再次使用获取全部文章接口看一下,如图:
新记录确实添加成功。
最后, 还是通过Apifox,我们发送一个删除ID为2的文章请求,如图:
从Apifox返回的结果来看,确实删除成功了, 现在再获取一下全部文章,如图:
所有接口全部验证成功。
分享标题:用Go实现一个带缓存的RESTAPI服务端
文章转载:http://www.csdahua.cn/qtweb/news49/499099.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网