前言

代码参考自《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")
}

[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. 数据治理之关键环节元数据管理开源项目datahub探索

    @ 目录 概述 定义 核心功能 概念 元数据应用 其他开源 架构 概览 组件 元数据摄取架构 服务体系结构 本地部署 环境要求 安装 摄取样例 摄取入门 介绍 核心概念 命令行MySQL摄取示例 配置 ...

  2. 卧槽Winform也可以这么好看?

    Winform也可以这么好看? 对于Winform很多人的刻板印象就是拖拉拽,简单生产界面,但是这样对于界面的效果,它并不会很好,虽然简单,快,但是效果也是极差,所以有很多人就去使用WPF,去写xml ...

  3. 2022-09-07:给你一个由正整数组成的数组 nums 。 数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数。 例如,序列 [4,6,16] 的最大公约数是 2 。 数组的一个

    2022-09-07:给你一个由正整数组成的数组 nums . 数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数. 例如,序列 [4,6,16] 的最大公约数是 2 . 数组的一个 ...

  4. 2020-10-23:go中channel的创建流程是什么?

    福哥答案2020-10-23:1.元素大小是否小于2的16次方,否则throw.2.对齐检查,否则throw.3.元素大小和容量的乘积不能超出范围,否则panic.4.生成*hchan,设置buf.4 ...

  5. 500行代码手写docker开篇-goland远程编译环境配置

    (1)500行代码手写docker开篇-goland远程编译环境配置 本系列教程主要是为了弄清楚容器化的原理,纸上得来终觉浅,绝知此事要躬行,理论始终不及动手实践来的深刻,所以这个系列会用go语言实现 ...

  6. 在开发过程中使用git rebase还是git merge,优缺点分别是什么?

    前言 在开发过程中,git rebase 和 git merge 都是常见的代码版本管理工具.它们都能够将分支合并到主分支,并且都有各自的优缺点. git merge git merge 是一种将两个 ...

  7. 工欲善其事必先利其器--CMake牛刀小试

    这里假设用户已经安装好MinGW编译套件!并配置好环境变量!具体怎么下载和配置网上教程非常多,这里贴上一个链接:不仅教你安装MinGW还教你安装VScode配置 1.学习c plus plus编码为什 ...

  8. 如何科学地利用MTTR优化软件交付流程?

    谷歌提出的衡量 DevOps 质量的 DORA 指标让 MTTR(平均恢复时间) 名声大振.在本文中,你将了解到 MTTR 的作用.为什么它对行业研究很有用.你可能被它误导的原因以及如何避免 MTTR ...

  9. R 绘制 GWAS 研究的 Manhattan 图

    曼哈顿图本质上是一个散点图,用于显示大量非零大范围波动数值,最早应用于全基因组关联分析(GWAS)研究展示高度相关位点.它得名源于样式与曼哈顿天际线相似(如下图). 近几年,在宏基因组领域,尤其是差异 ...

  10. 一次有关 DNS 解析导致 APP 慢的问题探究

    目录 一.业务背景 二. 问题 三.问题排查 3.1.问题一: 基于DNS 延迟的解析 3.2.问题二:HTTPDNS侧 HTTPDNS基础理论 相关问题 四.优化方向 4.1.域名解析配置 4.2. ...