帶著問題,找答案:
通過本片文章,你會了解以下四點。并且我會給出go語言的實現案例。
1、了解restful風格的來源、起源、演變史
2、了解restful風格的定義、含義
3、掌握restful風格的簡單運用
4、做一個小demo
在restful中前進,是一個非常有趣的過程。
一、他打哪來?為解決什么而去?
1、他爹是誰?
是個叫Roy Fielding的博士,是曾經參與開發http協議(現在上網的基礎規則)的主力之一。
2、為啥發明?
2000年那會,網上資源凌亂不堪。傳遞信息時。前后端交互時,亂操作http (如:用GET、POST亂傳參數)。大佬不愧是大佬,roy fielding博士,敏銳的發現這一點。并在自己的論文中書寫出了一種規則(風格)。試圖平息這場混亂。(“讓網絡資源,能像圖書館中的書記一樣管理”)
目標是:讓Web服務?簡單、可擴展(加服務器就能扛更多人訪問)、無狀態(服務器不記仇,每次請求獨立)
二、restful的具體表現?
1、一切皆“資源”
互聯網上的(用戶、訂單、圖片...),每個資源都有一個唯一地址(URL),
比如: http://api.com/users (代表所有用戶)
2、用HTTP動詞操作資源
動作 | HTTP動詞 | 例子 | 作用 |
---|---|---|---|
查 | GET | GET /users/101 | 獲取101號用戶信息 |
增 | POST | POST /users | 創建新用戶 |
改(全量) | PUT | PUT /users/101 | 更新101號全部信息 |
刪 | DELETE | DELETE /users/101 | 刪除101號用戶 |
改(局部) | PATCH | PATCH /users/101 | 只改用戶昵稱 |
3、返回必帶狀態碼
- 200 ok:成功
- 201 Created:創建成功
- 404 Not Found:資源不存在
....
三、Restful的意義!
1、結束亂的時代,從前url隨意設定。如:/getUser?id=1、/delete_order?oid=2...
? ? ?現在通過URL+HTTP動詞,讓全天下的程序員都能看懂。
2、只要按照這一套標準、這同一種風格。無論是go還是C、C++、Java等其他語言。都能通過接口調用,流暢的配合實現某種功能。
3、冪等安全:冪-就是多次。同一操作,連續執行多次,效果是一樣的。如delete一個條數據多次,效果與僅delete一次,是相同的。
在進行實戰演練前,你需要掌握(go基礎知識、http相關知識、數據庫相關知識)
四、實戰演練
跟著本博主的思路,一點一點來,包教會。
第一步:通過一個及其簡單的代碼入門。
1、入門版:
目標:掌握·通過http動詞的變換進行不同的操作。
package mainimport ("encoding/json""net/http"
)// 用戶結構體
type User struct {ID int `json:"id"`Name string `json:"name"`
}// 內存存儲(代替數據庫)
var users = []User{{ID: 1, Name: "張三"},{ID: 2, Name: "李四"},
}func main() {// 注冊路由:處理 /users 的所有請求http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {// 設置響應頭(告訴客戶端返回的是JSON)w.Header().Set("Content-Type", "application/json")switch r.Method {case "GET": // 獲取用戶列表json.NewEncoder(w).Encode(users)case "POST": // 創建新用戶var newUser User// 解析客戶端發來的JSON數據if err := json.NewDecoder(r.Body).Decode(&newUser); err != nil {w.WriteHeader(http.StatusBadRequest) // 400 錯誤return}// 模擬ID生成newUser.ID = len(users) + 1users = append(users, newUser)w.WriteHeader(http.StatusCreated) // 201 創建成功json.NewEncoder(w).Encode(newUser)default:w.WriteHeader(http.StatusMethodNotAllowed) // 405 不允許的方法}})// 啟動服務器(端口8080)http.ListenAndServe(":8080", nil)
}
2、基礎版:
將入門版本的拓展開來:通過函數調用實現。
package mainimport ("encoding/json" // 用于JSON處理"fmt" // 格式化輸出"log" // 日志記錄"net/http" // HTTP服務
)// 定義用戶結構體(相當于數據模型)
type User struct {ID int `json:"id"` // 用戶IDName string `json:"name"` // 用戶名
}// 內存數據庫(暫時替代真實數據庫)
var users = []User{{ID: 1, Name: "小明"},{ID: 2, Name: "小紅"},
}func main() {fmt.Println("👉 啟動RESTful服務器: http://localhost:8080")// 注冊路由:當訪問 /users 時觸發處理函數http.HandleFunc("/users", usersHandler)// 啟動服務器(監聽8080端口)log.Fatal(http.ListenAndServe(":8080", nil))
}// 處理/users路由的請求
func usersHandler(w http.ResponseWriter, r *http.Request) {// 設置響應頭(告訴瀏覽器返回的是JSON)w.Header().Set("Content-Type", "application/json")switch r.Method {case "GET": // 處理GET請求(查詢用戶)handleGetUsers(w, r)case "POST": // 處理POST請求(創建用戶)handleCreateUser(w, r)default: // 其他請求方法不允許w.WriteHeader(http.StatusMethodNotAllowed) // 405錯誤fmt.Fprintf(w, `{"error": "不支持該方法"}`)}
}// 處理GET請求(獲取所有用戶)
func handleGetUsers(w http.ResponseWriter, r *http.Request) {// 將用戶列表轉為JSON格式jsonData, err := json.Marshal(users)if err != nil {w.WriteHeader(http.StatusInternalServerError) // 500錯誤fmt.Fprintf(w, `{"error": "數據轉換失敗"}`)return}// 返回JSON數據w.Write(jsonData)
}// 處理POST請求(創建新用戶)
func handleCreateUser(w http.ResponseWriter, r *http.Request) {// 1. 解析請求中的JSON數據var newUser Usererr := json.NewDecoder(r.Body).Decode(&newUser)if err != nil {w.WriteHeader(http.StatusBadRequest) // 400錯誤fmt.Fprintf(w, `{"error": "無效的JSON數據"}`)return}// 2. 簡單的數據驗證if newUser.Name == "" {w.WriteHeader(http.StatusBadRequest)fmt.Fprintf(w, `{"error": "用戶名不能為空"}`)return}// 3. 生成新ID(實際項目中數據庫會自動生成)newUser.ID = len(users) + 1// 4. 添加到用戶列表users = append(users, newUser)// 5. 返回創建成功的響應w.WriteHeader(http.StatusCreated) // 201狀態碼json.NewEncoder(w).Encode(newUser)
}
原理圖:?
客戶端 (瀏覽器/curl)│▼HTTP請求(GET/POST)│▼Go服務器 (main.go)│├── GET /users → 返回用戶列表│└── POST /users → 創建新用戶│ ├── 解析JSON│ ├── 驗證數據│ └── 添加到內存│▼HTTP響應(JSON數據)
3、進階版:
添加獲取單個用戶功能GET / users / {id} )(如:get/users/1)
// 在main函數中添加新路由
func main() {// ...原有代碼...http.HandleFunc("/users/", userHandler) // 添加帶ID的路由
}// 新增處理函數
func userHandler(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")// 從路徑中提取ID:/users/123 → 123idStr := strings.TrimPrefix(r.URL.Path, "/users/")id, err := strconv.Atoi(idStr)if err != nil {w.WriteHeader(http.StatusBadRequest)fmt.Fprintf(w, `{"error": "無效的用戶ID"}`)return}// 查找用戶var foundUser *Userfor _, u := range users {if u.ID == id {foundUser = &ubreak}}if foundUser == nil {w.WriteHeader(http.StatusNotFound) // 404fmt.Fprintf(w, `{"error": "用戶不存在"}`)return}json.NewEncoder(w).Encode(foundUser)
}
恭喜走出新手村!
到這里,差不多,大家就已經明白了Restful風格是什么?怎么用。
后續若抽出時間,我會繼續更新呦~😉
謹記:
RESTful = 用HTTP動詞(GET/POST...)操作網絡資源(URI標識),
目標是簡單、統一、好擴展。
簡稱:"動詞操作資源地址",記住這點,你對restful的理解就能掌握90%了?