前言

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

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

设计模型和API

模型

  1. type Recipe struct {
  2. // 菜品名
  3. Name string `json:"name"`
  4. // 菜品标签,字符串切片
  5. Tags []string `json:"tags"`
  6. // 菜品材料
  7. Ingredients []string `json:"ingredients"`
  8. // 制作步骤
  9. Instructions []string `json:"instructions"`
  10. // 发布时间
  11. PublishedAt time.Time `json:"publishedAt"`
  12. }

API

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

实现接口

添加一个新食谱

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

获取所有食谱

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

根据食谱id更新食谱

  1. func UpdateRecipeHandler(c *gin.Context) {
  2. // PUT /recipes/:id
  3. id := c.Param("id")
  4. var recipe Recipe
  5. if err := c.ShouldBindJSON(&recipe); err != nil {
  6. c.JSON(http.StatusBadRequest, gin.H{
  7. "error": err.Error(),
  8. })
  9. return
  10. }
  11. index := -1
  12. // 根据id遍历查询
  13. for i := 0; i < len(recipes); i++ {
  14. if recipes[i].ID == id {
  15. index = i
  16. }
  17. }
  18. if index == -1 {
  19. c.JSON(http.StatusNotFound, gin.H{
  20. "error": "Recipe Not Found",
  21. })
  22. return
  23. }
  24. recipe.ID = id
  25. recipes[index] = recipe
  26. c.JSON(http.StatusOK, recipe)
  27. }
  28. func main(){
  29. router.PUT("/recipes/:id", UpdateRecipeHandler)
  30. }
  • python测试
  1. def put_test(data, id):
  2. url = f"http://127.0.0.1:8080/recipes/{id}"
  3. # data["id"] = id
  4. resp = requests.put(url=url, data=json.dumps(data))
  5. print("put test")
  6. print(resp.text)
  7. data2 = {
  8. "name": "西红柿炒鸡蛋",
  9. "tags": ["家常菜", "新手必会"],
  10. "ingredients": [
  11. "2个鸡蛋",
  12. "1个番茄, 切片",
  13. "葱花, 蒜瓣等",
  14. ],
  15. "instructions": [
  16. "步骤1",
  17. "步骤2",
  18. "步骤3",
  19. ],
  20. }
  21. put_test(data2, id="someidstring")

根据id删除食谱

  1. func DeleteRecipeHandler(c *gin.Context) {
  2. // DELETE /recipes/:id
  3. id := c.Param("id")
  4. index := -1
  5. // 根据id遍历查询
  6. for i := 0; i < len(recipes); i++ {
  7. if recipes[i].ID == id {
  8. index = i
  9. }
  10. }
  11. if index == -1 {
  12. c.JSON(http.StatusNotFound, gin.H{
  13. "error": "Recipe Not Found",
  14. })
  15. return
  16. }
  17. // 通过切片切割实现删除元素
  18. recipes = append(recipes[:index], recipes[index+1:]...)
  19. c.JSON(http.StatusOK, gin.H{
  20. "message": "Recipe has been deleted",
  21. })
  22. }
  23. func main(){
  24. router.DELETE("/recipes/:id", DeleteRecipeHandler)
  25. }
  • python测试
  1. def delete_test(id):
  2. url = f"http://127.0.0.1:8080/recipes/{id}"
  3. resp = requests.delete(url=url)
  4. print("delete test")
  5. print(resp.text)
  6. delete_test(id="someIdString")

根据标签搜索食谱

  1. func SearchRecipeHandler(c *gin.Context) {
  2. // GET /recipes/search
  3. tag := c.Query("tag")
  4. listOfRecipes := make([]Recipe, 0)
  5. for i := 0; i < len(recipes); i++ {
  6. found := false
  7. for _, t := range recipes[i].Tags {
  8. if strings.EqualFold(t, tag) {
  9. found = true
  10. }
  11. }
  12. if found {
  13. listOfRecipes = append(listOfRecipes, recipes[i])
  14. }
  15. }
  16. c.JSON(http.StatusOK, listOfRecipes)
  17. }
  18. func main(){
  19. router.GET("/recipes/search", SearchRecipeHandler)
  20. }
  • python测试
  1. def get_test_search(tag):
  2. url = f"http://127.0.0.1:8080/recipes/search?tag={tag}"
  3. resp = requests.get(url=url)
  4. print("get test search")
  5. print(resp.text)
  6. get_test_search(tag="家常菜")

完整示例代码

  1. package main
  2. import (
  3. "net/http"
  4. "strings"
  5. "time"
  6. "github.com/gin-gonic/gin"
  7. "github.com/rs/xid"
  8. )
  9. type Recipe struct {
  10. ID string `json:"id"`
  11. Name string `json:"name"`
  12. Tags []string `json:"tags"`
  13. Ingredients []string `json:"ingredients"`
  14. Instructions []string `json:"instructions"`
  15. PublishedAt time.Time `json:"publishedAt"`
  16. }
  17. // 保存recipes
  18. var recipes []Recipe
  19. func init() {
  20. recipes = make([]Recipe, 0)
  21. }
  22. func NewRecipeHandler(c *gin.Context) {
  23. // POST /recipes。创建新食谱
  24. var recipe Recipe
  25. if err := c.ShouldBindJSON(&recipe); err != nil {
  26. c.JSON(http.StatusBadRequest, gin.H{
  27. "error": err.Error(),
  28. })
  29. return
  30. }
  31. recipe.ID = xid.New().String()
  32. recipe.PublishedAt = time.Now()
  33. recipes = append(recipes, recipe)
  34. c.JSON(http.StatusOK, recipe)
  35. }
  36. func ListRecipesHandler(c *gin.Context) {
  37. c.JSON(http.StatusOK, recipes)
  38. }
  39. func UpdateRecipeHandler(c *gin.Context) {
  40. // PUT /recipes/:id
  41. id := c.Param("id")
  42. var recipe Recipe
  43. if err := c.ShouldBindJSON(&recipe); err != nil {
  44. c.JSON(http.StatusBadRequest, gin.H{
  45. "error": err.Error(),
  46. })
  47. return
  48. }
  49. index := -1
  50. for i := 0; i < len(recipes); i++ {
  51. if recipes[i].ID == id {
  52. index = i
  53. }
  54. }
  55. if index == -1 {
  56. c.JSON(http.StatusNotFound, gin.H{
  57. "error": "Recipe Not Found",
  58. })
  59. return
  60. }
  61. recipe.ID = id
  62. recipes[index] = recipe
  63. c.JSON(http.StatusOK, recipe)
  64. }
  65. func DeleteRecipeHandler(c *gin.Context) {
  66. // DELETE /recipes/:id
  67. id := c.Param("id")
  68. index := -1
  69. for i := 0; i < len(recipes); i++ {
  70. if recipes[i].ID == id {
  71. index = i
  72. }
  73. }
  74. if index == -1 {
  75. c.JSON(http.StatusNotFound, gin.H{
  76. "error": "Recipe Not Found",
  77. })
  78. return
  79. }
  80. recipes = append(recipes[:index], recipes[index+1:]...)
  81. c.JSON(http.StatusOK, gin.H{
  82. "message": "Recipe has been deleted",
  83. })
  84. }
  85. func SearchRecipeHandler(c *gin.Context) {
  86. // GET /recipes/search
  87. tag := c.Query("tag")
  88. listOfRecipes := make([]Recipe, 0)
  89. for i := 0; i < len(recipes); i++ {
  90. found := false
  91. for _, t := range recipes[i].Tags {
  92. if strings.EqualFold(t, tag) {
  93. found = true
  94. }
  95. }
  96. if found {
  97. listOfRecipes = append(listOfRecipes, recipes[i])
  98. }
  99. }
  100. c.JSON(http.StatusOK, listOfRecipes)
  101. }
  102. func main() {
  103. router := gin.Default()
  104. router.POST("/recipes", NewRecipeHandler)
  105. router.GET("/recipes", ListRecipesHandler)
  106. router.PUT("/recipes/:id", UpdateRecipeHandler)
  107. router.DELETE("/recipes/:id", DeleteRecipeHandler)
  108. router.GET("/recipes/search", SearchRecipeHandler)
  109. router.Run("127.0.0.1:8080")
  110. }

[gin]基于切片实现crud的更多相关文章

  1. 基于mybatis的CRUD

    u  基于Mybatis的CRUD u  掌握MyBatis的结果类型-resultMap和resultType u  掌握MyBatis的参数类型 u  掌握#和$两种语法 1      基于myb ...

  2. SpringMVC 学习笔记(五) 基于RESTful的CRUD

    1.1. 概述 当提交的表单带有_method字段时,通过HiddenHttpMethodFilter 将 POST 请求转换成 DELETE.PUT请求,加上@PathVariable注解从而实现  ...

  3. Mybatis基于SqlSession实现CRUD

    之前我们讲的基于XML还是接口注解配置都是使用接口实现CRUD,本文我们将要讲解通过splsession来实现CRUD,这种方法比较灵活. 基本配置 <!-- spring和MyBatis完美整 ...

  4. [深度学习] 基于切片辅助超推理库SAHI优化小目标识别

    对象检测是迄今为止计算机视觉中最重要的应用领域.然而,小物体的检测和大图像的推理仍然是实际使用中的主要问题,这是因为小目标物体有效特征少,覆盖范围少.小目标物体的定义通常有两种方式.一种是绝对尺度定义 ...

  5. MVC基于Struts2的CRUD,java+bean+struts

    1,所需jar包,将jar包导入lib中 2,项目目录结构 3,struts.xml <?xml version="1.0" encoding="UTF-8&quo ...

  6. 基于SSM的CRUD项目的详解

    创一个maven工程 创建web的目录和web.xml------------右击项目,build projet--->configure  project---->Project fac ...

  7. 基于SSM之Mybatis接口实现增删改查(CRUD)功能

    国庆已过,要安心的学习了. SSM框架以前做过基本的了解,相比于ssh它更为优秀. 现基于JAVA应用程序用Mybatis接口简单的实现CRUD功能: 基本结构: (PS:其实这个就是用的Mapper ...

  8. 一步步学Mybatis-实现单表情况下的CRUD操作 (3)

    今天这一章要紧接上一讲中的东西,本章中创建基于单表操作的CRUD与GetList操作,此示例中以Visitor表为范例,为了创建一点测试数据我们先弄个Add方法吧 继续在上次的IVisitorOper ...

  9. 第四章 go语言 数组、切片和映射

    文章由作者马志国在博客园的原创,若转载请于明显处标记出处:http://www.cnblogs.com/mazg/ 数组是由同构的元素组成.结构体是由异构的元素组成.数据和结构体都是有固定内存大小的数 ...

  10. Go语言类型(布尔、整型、数组、切片、map等)

    1.基本类型 布尔类型:bool 注意:布尔类型不能接受其他类型的赋值,不支持自动或强制的类型转换. 整型:int8.byte(uint8).int16.int.uint.uintptr int.ui ...

随机推荐

  1. .NET Core 离线生成 Tron 波场私钥和地址笔记

    NuGet 引入依赖库 PM> Install-Package Tron.Wallet.Net 随机生成私钥和对应的地址 using Tron.Wallet.Net; namespace Con ...

  2. jQuery实现swipe事件

    // jQuery.event.swipe // 0.5 // Stephen Band // Dependencies // jQuery.event.move 1.2 // One of swip ...

  3. 2023-03-30:用Go语言改写FFmpeg示例decode_audio.c,实现高效音频解码。

    2023-03-30:用Go语言改写FFmpeg示例decode_audio.c,实现高效音频解码. 答案2023-03-30: 这个程序的主要功能是将 MP2 音频文件解码为 PCM 格式,并输出到 ...

  4. 2022-11-15:这里有 n 个航班,它们分别从 1 到 n 进行编号。 有一份航班预订表 bookings , 表中第 i 条预订记录 bookings[i] = [firsti, lasti,

    2022-11-15:这里有 n 个航班,它们分别从 1 到 n 进行编号. 有一份航班预订表 bookings , 表中第 i 条预订记录 bookings[i] = [firsti, lasti, ...

  5. 2021-12-30:分裂问题。 一个数n,可以分裂成一个数组[n/2, n%2, n/2], 这个数组中哪个数不是1或者0,就继续分裂下去。 比如 n = 5,一开始分裂成[2, 1, 2], [2

    2021-12-30:分裂问题. 一个数n,可以分裂成一个数组[n/2, n%2, n/2], 这个数组中哪个数不是1或者0,就继续分裂下去. 比如 n = 5,一开始分裂成[2, 1, 2], [2 ...

  6. Django4全栈进阶之路1 Django4下载与安装

    python 下载安装: 下载网址:https://www.python.org/downloads/ 安装方法:https://www.cnblogs.com/beichengshiqiao/p/1 ...

  7. 深入理解 python 虚拟机:魔术方法之数学计算

    深入理解 python 虚拟机:魔术方法之数学计算 在本篇文章当中主要给大家介绍在 python 当中一些常见的魔术方法,本篇文章主要是关于与数学计算相关的一些魔术方法,在很多科学计算的包当中都使用到 ...

  8. 安装Visio 2016与原本的office冲突的最终解决方案

    一. 下载office visio 2016 二. 开始安装 但是提示卸载原本的office 三. 网上找寻答案 于是按照这篇文章https://jingyan.baidu.com/article/1 ...

  9. python基础:重新认识装饰器

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

  10. AntV L7 快速入门示例

    1. 引言 L7 地理空间数据可视分析引擎是一种基于 WebGL 技术的地理空间数据可视化引擎,可以用于实现各种地理空间数据可视化应用.L7 引擎支持多种数据源和数据格式,包括 GeoJSON.CSV ...