王的宝库头像
关注
CRUD 实战封面图

CRUD 实战

【Go 入门】CRUD 实战:增删改查,一篇讲透

上一篇我们把数据存进了数据库。这篇只干一件事:把最核心的四个操作——增、删、改、查(CRUD)讲透。


0. CRUD 是什么?

CRUD 是四个单词的缩写,所有软件都离不开这四个操作

字母全称中文举个例子
CCreate登记一本新书
RRead查看书单
UUpdate修改书的价格
DDelete下架一本书

类比:你逛的购物 App、刷的论坛,背后都是这四个操作。学会 CRUD,后端开发就入门了一半。


1. 增删改查 = 四个请求方法

在网页开发里,每个操作对应一个固定的"请求方法":

操作请求方法路径干什么
POST/api/books加一本书
GET/api/books看书单
PUT/api/books/:id改某本书
DELETE/api/books/:id删某本书

记忆口诀:POST 加,GET 看,PUT 改,DELETE 删。


2. 准备工作

新建一个项目,三步:

mkdir mybooks
cd mybooks
go mod init mybooks
go get github.com/gin-gonic/gin
go get gorm.io/gorm
go get github.com/glebarez/sqlite

第三个库 glebarez/sqlite 是纯 Go 的 SQLite 驱动,Windows 不用装编译器(上篇讲过)。


3. 全部代码(就一个 main.go)

在项目里新建 main.go,复制下面全部内容:

package main

import (
	"log"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"github.com/glebarez/sqlite"
	"gorm.io/gorm"
)

// Book 书的结构体,对应数据库里的 books 表
type Book struct {
	ID     uint    `json:"id" gorm:"primaryKey"`
	Title  string  `json:"title"`
	Author string  `json:"author"`
	Price  float64 `json:"price"`
}

func main() {
	// ===== 1. 连接数据库(books.db 就是一个文件)=====
	db, err := gorm.Open(sqlite.Open("books.db"), &gorm.Config{})
	if err != nil {
		log.Fatal("数据库连接失败:", err)
	}
	db.AutoMigrate(&Book{}) // 自动建表,没有 books 表就创建

	r := gin.Default()

	// ===== 2. 增:POST /api/books =====
	r.POST("/api/books", func(c *gin.Context) {
		var b Book
		// 前端发来的 JSON 填进 b
		if err := c.ShouldBindJSON(&b); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
		db.Create(&b) // 存进数据库,b.ID 自动填上
		c.JSON(http.StatusOK, gin.H{"data": b})
	})

	// ===== 3. 查:GET /api/books(全部)=====
	r.GET("/api/books", func(c *gin.Context) {
		var books []Book
		db.Find(&books) // 查出所有书
		c.JSON(http.StatusOK, gin.H{"data": books})
	})

	// ===== 4. 查:GET /api/books/1(单个)=====
	r.GET("/api/books/:id", func(c *gin.Context) {
		id, _ := strconv.Atoi(c.Param("id")) // 路径里的 1 是字符串,转成数字
		var b Book
		if err := db.First(&b, id).Error; err != nil { // 按 id 查
			c.JSON(http.StatusNotFound, gin.H{"error": "没有这本书"})
			return
		}
		c.JSON(http.StatusOK, gin.H{"data": b})
	})

	// ===== 5. 改:PUT /api/books/1 =====
	r.PUT("/api/books/:id", func(c *gin.Context) {
		id, _ := strconv.Atoi(c.Param("id"))
		var b Book
		if err := db.First(&b, id).Error; err != nil { // 先查出这本书
			c.JSON(http.StatusNotFound, gin.H{"error": "没有这本书"})
			return
		}
		if err := c.ShouldBindJSON(&b); err != nil { // 再填进新内容
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
		db.Save(&b) // 保存修改
		c.JSON(http.StatusOK, gin.H{"data": b})
	})

	// ===== 6. 删:DELETE /api/books/1 =====
	r.DELETE("/api/books/:id", func(c *gin.Context) {
		id, _ := strconv.Atoi(c.Param("id"))
		db.Delete(&Book{}, id) // 按 id 删除
		c.JSON(http.StatusOK, gin.H{"message": "删除成功"})
	})

	log.Println("服务启动:http://localhost:8080")
	r.Run(":8080")
}

核心就 5 个动作,记住这 5 行:

想做什么关键一行说明
db.Create(&b)插进数据库
查全部db.Find(&books)查出所有记录
查单个db.First(&b, id)按 id 查一条
db.Save(&b)保存修改
db.Delete(&Book{}, id)按 id 删除

每个操作都传了 &(地址),原因和上一篇 ShouldBindJSON(&t) 一样:要让函数真的改到我们的变量,必须告诉它变量放在哪。


4. 跑起来测一测

启动:

go run .

另开一个终端,按顺序敲:

# 增:加两本书
curl -X POST http://localhost:8080/api/books -H "Content-Type: application/json" -d '{"title":"Go 入门","author":"阿明","price":39.9}'

curl -X POST http://localhost:8080/api/books -H "Content-Type: application/json" -d '{"title":"Gin 实战","author":"小红","price":49.9}'

# 查全部
curl http://localhost:8080/api/books

# 查第 1 本
curl http://localhost:8080/api/books/1

# 改:把第 1 本价格改成 29.9
curl -X PUT http://localhost:8080/api/books/1 -H "Content-Type: application/json" -d '{"price":29.9}'

# 删:删掉第 2 本
curl -X DELETE http://localhost:8080/api/books/2

# 再看列表,应该只剩第 1 本,价格变成 29.9
curl http://localhost:8080/api/books

全走通,你的第一个完整增删改查就完成了。重启程序(Ctrl+C 再 go run .)再查一次,数据还在——因为存进了 books.db 文件。


5. 我踩过的 3 个坑

  1. 忘记写 &db.Create(&b)db.Find(&books)db.First(&b, id),不写 & 就是白干(函数改不到你的变量)
  2. 改数据用了 Create:改要用 Save,Create 是新增,会把一本书存成两本
  3. Windows 用了官方 SQLite 驱动gorm.io/driver/sqlite 要装编译器,用 github.com/glebarez/sqlite 直接跑

6. 总结

CRUD = 增(POST + Create)、查(GET + Find/First)、改(PUT + Save)、删(DELETE + Delete)。

真实项目里,代码会像系列第一篇那样拆成多个文件(model、handler、main),但核心永远是这 5 行数据库操作。把这篇跑通,你已经会写后端接口了。

下一篇可以给接口加登录功能(JWT 鉴权),或者讲讲多张表怎么关联。想看哪个评论区告诉我~


参考资料

  • GORM 官方文档(中文)— https://gorm.io/zh_CN/docs/
  • Gin 官方文档(中文)— https://gin-gonic.com/zh-cn/docs/

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/2302_79547686/article/details/165007459

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--