[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")
}
[gin]基于切片实现crud的更多相关文章
- 基于mybatis的CRUD
u 基于Mybatis的CRUD u 掌握MyBatis的结果类型-resultMap和resultType u 掌握MyBatis的参数类型 u 掌握#和$两种语法 1 基于myb ...
- SpringMVC 学习笔记(五) 基于RESTful的CRUD
1.1. 概述 当提交的表单带有_method字段时,通过HiddenHttpMethodFilter 将 POST 请求转换成 DELETE.PUT请求,加上@PathVariable注解从而实现 ...
- Mybatis基于SqlSession实现CRUD
之前我们讲的基于XML还是接口注解配置都是使用接口实现CRUD,本文我们将要讲解通过splsession来实现CRUD,这种方法比较灵活. 基本配置 <!-- spring和MyBatis完美整 ...
- [深度学习] 基于切片辅助超推理库SAHI优化小目标识别
对象检测是迄今为止计算机视觉中最重要的应用领域.然而,小物体的检测和大图像的推理仍然是实际使用中的主要问题,这是因为小目标物体有效特征少,覆盖范围少.小目标物体的定义通常有两种方式.一种是绝对尺度定义 ...
- MVC基于Struts2的CRUD,java+bean+struts
1,所需jar包,将jar包导入lib中 2,项目目录结构 3,struts.xml <?xml version="1.0" encoding="UTF-8&quo ...
- 基于SSM的CRUD项目的详解
创一个maven工程 创建web的目录和web.xml------------右击项目,build projet--->configure project---->Project fac ...
- 基于SSM之Mybatis接口实现增删改查(CRUD)功能
国庆已过,要安心的学习了. SSM框架以前做过基本的了解,相比于ssh它更为优秀. 现基于JAVA应用程序用Mybatis接口简单的实现CRUD功能: 基本结构: (PS:其实这个就是用的Mapper ...
- 一步步学Mybatis-实现单表情况下的CRUD操作 (3)
今天这一章要紧接上一讲中的东西,本章中创建基于单表操作的CRUD与GetList操作,此示例中以Visitor表为范例,为了创建一点测试数据我们先弄个Add方法吧 继续在上次的IVisitorOper ...
- 第四章 go语言 数组、切片和映射
文章由作者马志国在博客园的原创,若转载请于明显处标记出处:http://www.cnblogs.com/mazg/ 数组是由同构的元素组成.结构体是由异构的元素组成.数据和结构体都是有固定内存大小的数 ...
- Go语言类型(布尔、整型、数组、切片、map等)
1.基本类型 布尔类型:bool 注意:布尔类型不能接受其他类型的赋值,不支持自动或强制的类型转换. 整型:int8.byte(uint8).int16.int.uint.uintptr int.ui ...
随机推荐
- 【深入浅出 Yarn 架构与实现】6-3 NodeManager 分布式缓存
不要跳过这部分知识,对了解 NodeManager 本地目录结构,和熟悉 Container 启动流程有帮助. 一.分布式缓存介绍 主要作用就是将用户应用程序执行时,所需的外部文件资源下载缓存到各个节 ...
- 音视频八股文(11)-- ffmpeg avio 内存输入和内存输出。内存输出有完整代码,网上很少有的。
1.avio介绍 avio是FFmpeg中的一个模块,用于实现多种输入输出方式的封装. avio提供了一系列API,可以将数据从内存读取到缓冲区中,也可以将缓冲区中的数据写入到内存中.其实现依赖于IO ...
- 【设计模式】使用 go 语言实现简单工厂模式
最近在看<大话设计模式>,这本书通过对话形式讲解设计模式的使用场景,有兴趣的可以去看一下. 第一篇讲的是简单工厂模式,要求输入两个数和运算符号,得到运行结果. 这个需求不难,难就难在类要怎 ...
- Django4全栈进阶之路1 Django4下载与安装
python 下载安装: 下载网址:https://www.python.org/downloads/ 安装方法:https://www.cnblogs.com/beichengshiqiao/p/1 ...
- ArcGIS如何自动获得随机采样点?
本文介绍基于ArcMap软件,实现在指定区域自动生成随机点的方法. 在GIS应用中,我们时常需要在研究区域内进行地理数据的随机采样:而采样点的位置往往需要在结合实际情况的前提下,用计算机随机生 ...
- 【CF】Round #618 div2 C(文末有技巧)
目录 round #618 div2 C(文末有技巧) 题目: 样例输入输出 思路 小技巧(拿小本本记下来) round #618 div2 C(文末有技巧) 这是题目链接->链接 题目: 原题 ...
- Mac常用文件解压命令
tar 解压:tar xvf fileName.tar 压缩:tar cvf fileName.tar directoryName rar 1.安装rar 下载RAR https://www.rarl ...
- K2C V21.4.6.12刷breed教程
K2C V21.4.6.12刷breed教程(刷机方法源自qiao99) 原贴地址:K2C V21.4.6.12刷breed记录 http://www.right.com.cn/forum/threa ...
- java开发学习框架
Java基础 1.1. Java简介与安装 1.2. Java基本语法 1.3. 数据类型与变量 1.4. 运算符与表达式 1.5. 流程控制(分支与循环) 1.6. 数组 面向对象编程 2.1. 类 ...
- wireshark分析tcp传输之文件上传速率问题
在网络性能问题排查思路那一节里,我提到了查看系统网络瓶颈的方法以及排查丢包问题的手段. 但就此分析网络问题还不够精细,有时网络资源并没有达到瓶颈,或者并没有丢包产生,但是网络传输速率就是很慢,或者有丢 ...