带着问题,找答案:
通过本片文章,你会了解以下四点。并且我会给出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 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、基础版:
将入门版本的拓展开来:通过函数调用实现。
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) }
原理图:
客户端 (浏览器/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 → 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%了