[gin]基于切片实现crud

简介: [gin]基于切片实现crud

前言

代码参考自《Building Distributed Application in Gin》

需求:设计一个食谱相关的API,数据存放到切片中。

设计模型和API

模型

type Recipe struct {
  // 菜品名
  Name         string    `json:"name"`
  // 菜品标签,字符串切片
  Tags         []string  `json:"tags"`
  // 菜品材料
  Ingredients  []string  `json:"ingredients"`
  // 制作步骤
  Instructions []string  `json:"instructions"`
  // 发布时间
  PublishedAt  time.Time `json:"publishedAt"`
}

API

http method resource description
GET /recipes 返回一列recipe数据
POST /recipes 创建新食谱
PUT /recipes/{id} 更新一个已存在的食谱
DELETE /recipes/{id} 删除一个已存在的食谱
GET /recipes/search?tag=X 根据标签查询食谱

实现接口

添加一个新食谱

  • POST /recipes
package main
import (
  "net/http"
  "strings"
  "time"
  "github.com/gin-gonic/gin"
  "github.com/rs/xid"
)
type Recipe struct {
  ID           string    `json:"id"`
  Name         string    `json:"name"`
  Tags         []string  `json:"tags"`
  Ingredients  []string  `json:"ingredients"`
  Instructions []string  `json:"instructions"`
  PublishedAt  time.Time `json:"publishedAt"`
}
// 保存recipes数据
var recipes []Recipe
func init() {
  recipes = make([]Recipe, 0)
}
func NewRecipeHandler(c *gin.Context) {
  // POST /recipes。创建新食谱
  var recipe Recipe
  if err := c.ShouldBindJSON(&recipe); err != nil {
    c.JSON(http.StatusBadRequest, gin.H{
      "error": err.Error(),
    })
    return
  }
  recipe.ID = xid.New().String()
  recipe.PublishedAt = time.Now()
  recipes = append(recipes, recipe)
  c.JSON(http.StatusOK, recipe)
}
func main(){
  router := gin.Default()
    router.POST("/recipes", NewRecipeHandler)
    router.Run("127.0.0.1:8080")
}
  • 使用python进行测试
import requests
import json
def post_test(data):
    url = "http://127.0.0.1:8080/recipes"
    resp = requests.post(url=url, data=json.dumps(data))
    print("post test")
    print(resp.text)
if __name__ == "__main__":
    data1 = {
        "name": "Homemade Pizza",
        "tags": ["italian", "pizza", "dinner"],
        "ingredients": [
            "1 1/2 cups (355 ml) warm water (105°F-115°F)",
            "1 package (2 1/4 teaspoons) of active dry yeast",
            "3 3/4 cups (490 g) bread flour",
            "feta cheese, firm mozzarella cheese, grated",
        ],
        "instructions": [
            "Step 1.",
            "Step 2.",
            "Step 3.",
        ],
    }
    post_test(data1)

获取所有食谱

  • GET /recipes
func ListRecipesHandler(c *gin.Context) {
  c.JSON(http.StatusOK, recipes)
}
func main(){
  router.GET("/recipes", ListRecipesHandler)
}
  • python测试
def get_test():
    url = "http://127.0.0.1:8080/recipes"
    resp = requests.get(url)
    print("get test")
    print(resp.text)
get_test()

根据食谱id更新食谱

func UpdateRecipeHandler(c *gin.Context) {
  // PUT /recipes/:id
  id := c.Param("id")
  var recipe Recipe
  if err := c.ShouldBindJSON(&recipe); err != nil {
    c.JSON(http.StatusBadRequest, gin.H{
      "error": err.Error(),
    })
    return
  }
  index := -1
  // 根据id遍历查询
  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.ID = id
  recipes[index] = recipe
  c.JSON(http.StatusOK, recipe)
}
func main(){
  router.PUT("/recipes/:id", UpdateRecipeHandler)
}
  • python测试
def put_test(data, id):
    url = f"http://127.0.0.1:8080/recipes/{id}"
    # data["id"] = id
    resp = requests.put(url=url, data=json.dumps(data))
    print("put test")
    print(resp.text)
data2 = {
  "name": "西红柿炒鸡蛋",
  "tags": ["家常菜", "新手必会"],
  "ingredients": [
    "2个鸡蛋",
    "1个番茄, 切片",
    "葱花, 蒜瓣等",
  ],
  "instructions": [
    "步骤1",
    "步骤2",
    "步骤3",
  ],
}
put_test(data2, id="someidstring")

根据id删除食谱

func DeleteRecipeHandler(c *gin.Context) {
  // DELETE /recipes/:id
  id := c.Param("id")
  index := -1
  // 根据id遍历查询
  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
  }
  // 通过切片切割实现删除元素
  recipes = append(recipes[:index], recipes[index+1:]...)
  
  c.JSON(http.StatusOK, gin.H{
    "message": "Recipe has been deleted",
  })
}
func main(){
  router.DELETE("/recipes/:id", DeleteRecipeHandler)
}
  • python测试
def delete_test(id):
    url = f"http://127.0.0.1:8080/recipes/{id}"
    resp = requests.delete(url=url)
    print("delete test")
    print(resp.text)
delete_test(id="someIdString")

根据标签搜索食谱

func SearchRecipeHandler(c *gin.Context) {
  // GET /recipes/search
  tag := c.Query("tag")
  listOfRecipes := make([]Recipe, 0)
  for i := 0; i < len(recipes); i++ {
    found := false
    for _, t := range recipes[i].Tags {
      if strings.EqualFold(t, tag) {
        found = true
      }
    }
    if found {
      listOfRecipes = append(listOfRecipes, recipes[i])
    }
  }
  c.JSON(http.StatusOK, listOfRecipes)
}
func main(){
  router.GET("/recipes/search", SearchRecipeHandler)
}
  • python测试
def get_test_search(tag):
    url = f"http://127.0.0.1:8080/recipes/search?tag={tag}"
    resp = requests.get(url=url)
    print("get test search")
    print(resp.text)
get_test_search(tag="家常菜")

完整示例代码

package main
import (
  "net/http"
  "strings"
  "time"
  "github.com/gin-gonic/gin"
  "github.com/rs/xid"
)
type Recipe struct {
  ID           string    `json:"id"`
  Name         string    `json:"name"`
  Tags         []string  `json:"tags"`
  Ingredients  []string  `json:"ingredients"`
  Instructions []string  `json:"instructions"`
  PublishedAt  time.Time `json:"publishedAt"`
}
// 保存recipes
var recipes []Recipe
func init() {
  recipes = make([]Recipe, 0)
}
func NewRecipeHandler(c *gin.Context) {
  // POST /recipes。创建新食谱
  var recipe Recipe
  if err := c.ShouldBindJSON(&recipe); err != nil {
    c.JSON(http.StatusBadRequest, gin.H{
      "error": err.Error(),
    })
    return
  }
  recipe.ID = xid.New().String()
  recipe.PublishedAt = time.Now()
  recipes = append(recipes, recipe)
  c.JSON(http.StatusOK, recipe)
}
func ListRecipesHandler(c *gin.Context) {
  c.JSON(http.StatusOK, recipes)
}
func UpdateRecipeHandler(c *gin.Context) {
  // PUT /recipes/:id
  id := c.Param("id")
  var recipe Recipe
  if err := c.ShouldBindJSON(&recipe); err != nil {
    c.JSON(http.StatusBadRequest, gin.H{
      "error": err.Error(),
    })
    return
  }
  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.ID = id
  recipes[index] = recipe
  c.JSON(http.StatusOK, recipe)
}
func DeleteRecipeHandler(c *gin.Context) {
  // DELETE /recipes/:id
  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
  }
  recipes = append(recipes[:index], recipes[index+1:]...)
  c.JSON(http.StatusOK, gin.H{
    "message": "Recipe has been deleted",
  })
}
func SearchRecipeHandler(c *gin.Context) {
  // GET /recipes/search
  tag := c.Query("tag")
  listOfRecipes := make([]Recipe, 0)
  for i := 0; i < len(recipes); i++ {
    found := false
    for _, t := range recipes[i].Tags {
      if strings.EqualFold(t, tag) {
        found = true
      }
    }
    if found {
      listOfRecipes = append(listOfRecipes, recipes[i])
    }
  }
  c.JSON(http.StatusOK, listOfRecipes)
}
func main() {
  router := gin.Default()
  router.POST("/recipes", NewRecipeHandler)
  router.GET("/recipes", ListRecipesHandler)
  router.PUT("/recipes/:id", UpdateRecipeHandler)
  router.DELETE("/recipes/:id", DeleteRecipeHandler)
  router.GET("/recipes/search", SearchRecipeHandler)
  router.Run("127.0.0.1:8080")
}
相关文章
|
6月前
|
前端开发 关系型数据库 数据库
使用 Flask 连接数据库和用户登录功能进行数据库的CRUD
使用 Flask 连接数据库和用户登录功能进行数据库的CRUD
131 0
|
1月前
|
数据可视化 API PHP
学生信息管理系统-可视化-科目管理CRUD代码生成器
学生信息管理系统-可视化-科目管理CRUD代码生成器
35 5
|
2月前
|
前端开发 IDE 数据库连接
ThinkPHP6 模型层的模型属性,表映射关系,以及如何在控制层中使用模型层和模型层中的简单CRUD
本文详细介绍了ThinkPHP6中模型层的使用,包括模型属性设置、表映射关系、以及如何在控制层中使用模型层进行CRUD操作。
ThinkPHP6 模型层的模型属性,表映射关系,以及如何在控制层中使用模型层和模型层中的简单CRUD
|
3月前
|
前端开发 Java 关系型数据库
通过HTML网页对mysql数据库进行增删改查(CRUD实例)
通过HTML网页对mysql数据库进行增删改查(CRUD实例)
218 0
|
5月前
|
API
10.SPA项目开发之CRUD+表单验证
10.SPA项目开发之CRUD+表单验证
27 0
|
5月前
|
关系型数据库 MySQL 数据库
Mysql数据库操作CRUD
Mysql数据库操作CRUD
|
6月前
|
前端开发 数据库连接 数据库
ASP.NETMVC数据库完整CRUD操作示例
ASP.NETMVC数据库完整CRUD操作示例
68 0
|
6月前
|
SQL 关系型数据库 MySQL
『 MySQL数据库 』CRUD之UD,表的数据更新(修改)及删除
『 MySQL数据库 』CRUD之UD,表的数据更新(修改)及删除
|
6月前
|
关系型数据库 MySQL 数据处理
『 MySQL数据库 』表的增删查改(CRUD)之表的数据插入及基本查询(下)
『 MySQL数据库 』表的增删查改(CRUD)之表的数据插入及基本查询(下)
|
8天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
22 4