系列文章目录
第一章 gin初步认识
第二章 设置API
目录

注:
- 系列文章是对应上述英文原版书的学习笔记
- 相关自己的练习代码包含注释,放在在本人的gitee,欢迎star
- 所有内容允许转载,如果侵犯书籍的著作权益,请联系删除
- 笔记持续更新中
设置API
前言
本章将介绍如何构建RESTful API
,
介绍HTTP的其他方法和路由(router)的方法。
还有如何编写OpenAPI
和生成API
文档。
gin框架的微服务应用架构
简单的说就是,微服务通过暴露RESTful API
来管理http
协议下的方法(recipes)
定义数据模型
type Recipe struct {
Name string `json:"name"` // 使用注解指定字段
Tags []string `json:"tags"`
Ingredients []string `json:"ingredients"`
Instructions []string `json:"instructions"`
PublishedAt time.Time `json:"PublishedAt"`
}
在数据模型后面加上注解,有助于Go
和JSON
在字段名
http结点方法
实现HTTP路由
1. 定义全局变量,用来存储数据
使用数据库后,就可以直接使用数据库返回的数据
var recipes []Recipe
func init() {
recipes = make([]recipes, 0)
}
2. 编写POST响应处理函数
func NewRecipeHandler(c *gin.Context) {
var recipe Recipe
// 从POST请求的正文中获取并绑定到数据实体
// c.ShouldBindJSON(&recipe)
if err := c.ShouldBindJSON(&recipe); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error()})
return
}
// 生成独一无二的ID代码
recipe.ID = xid.New().String()
recipe.PublishedAt = time.Now()
recipes = append(recipes, recipe)
// 把数据模型实体recipe返回为json模式
c.JSON(http.Status(OK, recipe)
}
3. 编写GET响应函数
func ListRecipesHandler(c *gin.Context) {
c.JSON(http.StatusOK, recipes)
}
4. 从json
文件获取数据,初始化实体
func init() {
// 使用文本文件json模拟数据库用于初始化数据模型
recipes = make([]Recipe, 0)
// 一般go会在项目的root路径下寻找文件
file, _ := ioutil.ReadFile("recipes.json")
_ = json.Unmarshal([]byte(file), &recipes)
}
5. 编写PUT响应函数,更新指定数据
// URL传参ID,对指定的实体数据更新
func UpdateRecipeHandler(c *gin.Context) {
id := c.Param("id")
var recipe Recipe
// 1. 用body初始化实体
if err := c.ShouldBindJSON(&recipe); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error()})
return
}
// 在本地数据里面定位URL指定ID的recipe
index := -1
for i := 0; i < len(recipes); i++ {
if recipes[i].ID == id {
index = i
}
}
if index == -1 {
c.JSON(http.StatusNotFound, gin.H{
"error": "Recipe not found"})
return
}
// 把找到的recipe更新到本地数据
recipes[index] = recipe
c.JSON(http.StatusOK, recipe)
}
6. 编写DELETE响应函数,查找并删除指定实体
func DeleteRecipeHandler(c *gin.Context) {
id := c.Param("id")
index := -1
for i := 0; i < len(recipes); i++ {
if recipes[i].ID == id {
index = i
}
}
if index == -1 {
c.JSON(http.StatusNotFound, gin.H{
"error": "Recipe not found"})
return
}
// 数组拼接的方法删除下标为index的元素
recipes = append(recipes[:index], recipes[index+1:]...)
c.JSON(http.StatusOK, gin.H{
"message": "Recipe has been deleted"})
}
7. 编写GET/recipes/search?tag=?
响应函数
// URL传参ID,对指定的实体数据更新
func UpdateRecipeHandler(c *gin.Context) {
id := c.Param("id")
var recipe Recipe
// 1. 用body初始化实体
if err := c.ShouldBindJSON(&recipe); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error()})
return
}
// 在本地数据里面定位URL指定ID的recipe
index := -1
for i := 0; i < len(recipes); i++ {
if recipes[i].ID == id {
index = i
}
}
if index == -1 {
c.JSON(http.StatusNotFound, gin.H{
"error": "Recipe not found"})
return
}
// 把找到的recipe更新到本地数据
recipes[index] = recipe
c.JSON(http.StatusOK, recipe)
}
编写OpenAPI说明(OAS)
OAS作为API说明或者API定义语言,当你描述一个API的时候,应该包含如下的信息:
- API的基本信息
- 有效的路径和操作(HTTP方法)
- 每个操作对应的期待的输入(查询,路径参数,请求体等)和响应(HTTP状态码,响应体等)
使用Go Swagger生成API说明
- 在
package main
上一行,编写API的说明信息
// Recipes API
//
// This is a sample recipes API.
//
// Schemes: http
// host: localhost:8080
// BasePath: /
// Version: 1.0.0
// Contact: Mohamed Labouardy <mohamed@labourdy.com> https://labourardy.com
//
// Consumes:
// - application/json
//
// Produces:
// - application/json
// swagger:meta
在项目根目录执行
这件生成json类型的说明文档,如果后缀是yml
或者yaml
会生成YAML
文件
执行
将依据刚才生成的文档,渲染打开一个本地网站用于可视化展示文档
- 在Handler函数上编写特定的API的文档
// swagger:operation GET /recipes recipes listRecipes
// Returns list of recipes
// ---
// produces:
// - application/json
// responses:
// '200':
// description: Successful operation
func ListRecipesHandler(c *gin.Context) {
c.JSON(http.StatusOK, recipes)
}
// swagger:operation PUT /recipes/{id} recipes updateRecipe
// Update an existing recipe
// ---
// parameters:
// - name: id
// in: path
// description: ID of the recipe
// required: true
// type: string
// produces:
// - application/json
// responses:
// '200':
// description: Successful operation
func UpdateRecipeHandler(c *gin.Context)