REST(Representational State Transfer)是一種通過HTTP協議設計API的架構風格,用于構建分布式系統中的網絡應用程序。REST API(RESTful API)是基于這種設計風格的應用程序編程接口。其主要優點是其極大的靈活性, 只要需要直接從服務器向Web應用程序或站點的用戶提供數據, 開發人員直接使用REST API即可實現。
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 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))}
在本地運行服務端, 服務端將在本地監聽8080端口, 通過瀏覽器輸入: http://127.0.0.1:8080/articles, 該接口將獲取所有文章,如圖:
通過API接口通過文章ID查詢某一篇文章,接口請求如下:
新增一條新文章是POST請求, 這里主要通過Apifox發送POST請求,如圖:
從返回的結果來看, 成功添加了一條新記錄, 再次使用獲取全部文章接口看一下,如圖:
新記錄確實添加成功。
最后, 還是通過Apifox,我們發送一個刪除ID為2的文章請求,如圖:
從Apifox返回的結果來看,確實刪除成功了, 現在再獲取一下全部文章,如圖:
所有接口全部驗證成功。
本文鏈接:http://www.www897cc.com/showinfo-26-56402-0.html用Go實現一個帶緩存的REST API服務端
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 六種不同類型的K8s部署策略總結