带着问题,找答案:
通过本片文章,你会了解以下四点 。并且我会给出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动词 的变换 进行不同的操作。
Go
package main
import (
"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) + 1
users = 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、基础版:
将入门版本的拓展开来:通过函数调用实现。
Go
package main
import (
"encoding/json" // 用于JSON处理
"fmt" // 格式化输出
"log" // 日志记录
"net/http" // HTTP服务
)
// 定义用户结构体(相当于数据模型)
type User struct {
ID int `json:"id"` // 用户ID
Name 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 User
err := 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)
}
原理图:
bash
客户端 (浏览器/curl)
│
▼
HTTP请求(GET/POST)
│
▼
Go服务器 (main.go)
│
├── GET /users → 返回用户列表
│
└── POST /users → 创建新用户
│ ├── 解析JSON
│ ├── 验证数据
│ └── 添加到内存
│
▼
HTTP响应(JSON数据)
3、进阶版:
添加 获取单个用户功能GET / users / {id} )(如:get/users/1)
Go
// 在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 → 123
idStr := 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 *User
for _, u := range users {
if u.ID == id {
foundUser = &u
break
}
}
if foundUser == nil {
w.WriteHeader(http.StatusNotFound) // 404
fmt.Fprintf(w, `{"error": "用户不存在"}`)
return
}
json.NewEncoder(w).Encode(foundUser)
}
恭喜走出新手村!
到这里,差不多,大家就已经明白了Restful风格是什么?怎么用。
后续若抽出时间,我会继续更新呦~😉
谨记:
RESTful = 用HTTP动词(GET/POST...)操作网络资源(URI标识),
目标是简单、统一、好扩展。
简称:"动词操作资源地址",记住这点,你对restful的理解就能掌握90%了