网站首页 > 技术文章 正文
Go 实现restful接口CRUD操作范例(go+gin+mongo)
以下是使用Gin和MongoDB实现RESTful API CRUD操作的示例代码。
package main
import (
"context"
"fmt"
"log"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type Book struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
Title string `json:"title" bson:"title"`
Author string `json:"author" bson:"author"`
}
var collection *mongo.Collection
func main() {
// Connect to MongoDB
clientOptions := options.Client().ApplyURI("mongodb://192.168.6.145:27017")
client, err := mongo.Connect(context.Background(), clientOptions)
if err != nil {
log.Fatal(err)
}
// Check the connection
err = client.Ping(context.Background(), nil)
if err != nil {
log.Fatal(err)
}
collection = client.Database("books").Collection("books")
// Create a Gin router
router := gin.Default()
// Define book routes group
bookRoutes := router.Group("/v1/books")
{
bookRoutes.GET("", getBooks)
bookRoutes.GET("/:id", getBook)
bookRoutes.POST("", createBook)
bookRoutes.PUT("/:id", updateBook)
bookRoutes.DELETE("/:id", deleteBook)
}
// Start the server
router.Run(":8080")
}
func getBooks(c *gin.Context) {
// Find all books
cursor, err := collection.Find(context.Background(), bson.M{})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get books"})
return
}
var books []Book
if err := cursor.All(context.Background(), &books); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get books"})
return
}
c.JSON(http.StatusOK, books)
}
func getBook(c *gin.Context) {
// Get the book ID from the URL parameters
id, err := primitive.ObjectIDFromHex(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid book ID"})
return
}
// Find the book by ID
var book Book
err = collection.FindOne(context.Background(), bson.M{"_id": id}).Decode(&book)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Book not found"})
return
}
c.JSON(http.StatusOK, book)
}
func createBook(c *gin.Context) {
// Bind the JSON request body to a Book object
var book Book
if err := c.BindJSON(&book); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to parse request body"})
return
}
// Insert the book into the database
result, err := collection.InsertOne(context.Background(), book)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create book"})
return
}
// Set the book ID
book.ID = result.InsertedID.(primitive.ObjectID)
c.JSON(http.StatusCreated, book)
}
func updateBook(c *gin.Context) {
// Get the book ID from the URL parameters
id, err := primitive.ObjectIDFromHex(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid book ID"})
return
}
// Bind the JSON request body to a Book object
var book Book
if err := c.BindJSON(&book); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to parse request body"})
return
}
// Set the book ID
book.ID = id
// Update the book in the database
result, err := collection.ReplaceOne(context.Background(), bson.M{"_id": id}, book)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update book"})
return
}
if result.MatchedCount == 0 {
c.JSON(http.StatusNotFound, gin.H{"error": "Book not found"})
return
}
c.JSON(http.StatusOK, book)
}
func deleteBook(c *gin.Context) {
// Get the book ID from the URL parameters
id, err := primitive.ObjectIDFromHex(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid book ID"})
return
}
// Delete the book from the database
result, err := collection.DeleteOne(context.Background(), bson.M{"_id": id})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete book"})
return
}
if result.DeletedCount == 0 {
c.JSON(http.StatusNotFound, gin.H{"error": "Book not found"})
return
}
c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("Book with ID %s has been deleted", id.Hex())})
}
以下代码注解:
在这个代码中,使用 Golang + Gin + MongoDB 实现了一个简单的 RESTful API,用于管理书籍信息。以下是代码的主要部分注释解释:
- 导入所需的包,包括 "fmt"、"net/http"、"github.com/gin-gonic/gin"、"go.mongodb.org/mongo-driver/bson" 和 "go.mongodb.org/mongo-driver/mongo"。
- 定义了一个 Book 结构体,使用 bson 标签将结构体字段映射到 MongoDB 文档字段。ID 字段被定义为 primitive.ObjectID,它是 MongoDB 生成的唯一标识符。
- 定义了一个全局变量 collection,用于表示将用于存储书籍对象的 MongoDB 集合。使用 init() 函数设置 MongoDB 客户端并创建集合对象。
- 创建 Gin 路由器并定义了一个路由组,用于处理书籍 API 路由。每个路由使用 HTTP 方法和路由路径定义,并指定相应的路由处理函数。
- 每个路由处理函数都接收一个名为 c 的 *gin.Context 参数,以访问请求和响应对象。使用 c.JSON() 函数将 JSON 响应发送回客户端,并指定 HTTP 状态码和响应体。
- 在 createBook() 和 updateBook() 函数中,使用 c.BindJSON() 函数将请求体绑定到一个 Book 对象上。这个函数根据请求的 Content-Type 头部确定请求体的格式(JSON、XML 等),然后将请求体反序列化为 Book 对象。
- 在 getBook() 函数中,使用 c.Param("id") 从 URL 参数中检索出书籍的 ID。使用 bson.M{"_id": id} 查询在数据库中查找指定 ID 的书籍。
- 在 updateBook() 函数中,使用 $set 操作符仅更新书籍文档的 Title 和 Author 字段。使用 bson.M{"$set": bson.M{"title": book.Title, "author": book.Author}} 更新表达式更新数据库中的书籍。
- 在 deleteBook() 函数中,使用 bson.M{"_id": id} 查询删除数据库中具有指定 ID 的书籍。
- 在 main() 函数中,定义了一个监听地址和端口的 HTTP 服务器,并使用 router.Run() 函数启动服务器。
- 在 createBook()、updateBook() 和 deleteBook() 函数中,使用 collection.InsertOne()、collection.UpdateOne() 和 collection.DeleteOne() 函数向 MongoDB 中的集合添加、更新和删除文档。
- 在 getBooks() 函数中,使用 collection.Find() 函数查询集合中的所有文档。然后使用 c.JSON() 函数将响应作为 JSON 发送回客户端。
- 在 getBook()、updateBook() 和 deleteBook() 函数中,使用 collection.FindOne() 函数查询集合中的单个文档,并使用 c.JSON() 函数将响应作为 JSON 发送回客户端。
这个代码演示了如何使用 Golang + Gin + MongoDB 实现一个简单的 RESTful API,提供了基本的 CRUD 功能。使用路由组可以更好地组织和管理 API 路由,并使用 MongoDB 驱动程序在 Golang 中进行 MongoDB 操作。
补充说明一下这个代码中使用的一些技术和函数:
- Gin:Gin 是一个轻量级 Web 框架,具有快速路由和中间件支持,适合构建高性能 Web 应用程序。在这个代码中,我们使用 Gin 创建路由和处理 HTTP 请求和响应。
- MongoDB:MongoDB 是一个文档型 NoSQL 数据库,具有灵活的文档模型和可扩展性。在这个代码中,我们使用 MongoDB 存储和管理书籍信息。
- bson.M 和 bson.D:MongoDB 使用 BSON(二进制 JSON)格式存储数据,而 bson.M 和 bson.D 是 Golang 中用于表示 BSON 的映射和文档的类型。在这个代码中,我们使用 bson.M 和 bson.D 来构建 MongoDB 查询和更新操作的条件和表达式。
- c.JSON():Gin 的上下文对象(gin.Context)提供了一些有用的函数,例如 c.JSON(),用于向客户端发送 JSON 响应。c.JSON() 函数接受一个 HTTP 状态码和一个结构体或 map,并将其序列化为 JSON 格式,然后发送到客户端。
- c.Param():c.Param() 函数用于从 URL 参数中提取值。在这个代码中,我们使用 c.Param("id") 从 URL 中获取书籍的 ID。
- c.BindJSON():c.BindJSON() 函数用于将请求体绑定到一个结构体上。在这个代码中,我们使用 c.BindJSON() 函数将请求体反序列化为 Book 对象。
- collection.InsertOne()、collection.UpdateOne() 和 collection.DeleteOne():这些函数是 MongoDB Go 驱动程序中用于向集合中添加、更新和删除文档的函数。
- collection.Find() 和 collection.FindOne():这些函数是 MongoDB Go 驱动程序中用于从集合中检索文档的函数。collection.Find() 函数返回一个游标,可以迭代文档结果集。而 collection.FindOne() 函数返回一个单个文档结果。
bson.M 和bson.D作用解释
bson.M 和 bson.D 是 Golang 中用于表示 MongoDB BSON(Binary JSON)格式的映射和文档的类型。
- bson.M:它是一个 map 类型,其中键是字符串,值可以是任意类型。在 MongoDB 中,bson.M 通常用于表示查询或更新条件。它支持嵌套结构,可以使用点号(".")来表示嵌套字段。例如,{"name.first": "Alice"} 表示一个嵌套在 name 字段下的 first 字段。
- bson.D:它是一个有序的文档类型,其中每个元素都是一个键值对。在 MongoDB 中,bson.D 通常用于表示排序条件、投影条件、更新操作和聚合管道阶段。与 bson.M 不同,bson.D 是有序的,因此可以在其中指定字段的顺序。例如,bson.D{{"name", 1}, {"age", -1}} 表示按照 name 升序和 age 降序的顺序排序。
总的来说,bson.M 和 bson.D 都是用于在 Golang 和 MongoDB 之间进行数据交换的常用类型,它们简化了 MongoDB 的查询、更新、排序、投影等操作的实现过程,并提供了方便的 API 来操作 MongoDB 的 BSON 格式数据。
bson使用示例
这里给出几个 bson 使用示例,来更好地说明它的使用方法和作用。
创建一个 bson.M 对象:
doc := bson.M{
"name": "Alice",
"age": 25,
"addr": bson.M{
"city": "Beijing",
"country": "China",
},
}
这里创建了一个 bson.M 对象,其中包含了 name、age 和 addr 三个字段。其中,addr 是一个嵌套的 bson.M 对象,它包含了 city 和 country 两个字段。这个 bson.M 对象可以用于 MongoDB 的查询或更新操作,例如:
// 查询 age 大于 20 岁的文档
collection.Find(bson.M{"age": bson.M{"$gt": 20}})
// 更新 name 为 Bob 的文档的 age 字段为 30
collection.UpdateOne(bson.M{"name": "Bob"}, bson.M{"$set": bson.M{"age": 30}})
创建一个 bson.D 对象:
doc := bson.D{
{"name", "Bob"},
{"age", 30},
{"addr", bson.D{
{"city", "Beijing"},
{"country", "China"},
}},
}
这里创建了一个 bson.D 对象,其中包含了 name、age 和 addr 三个键值对。与 bson.M 不同的是,bson.D 是有序的,因此可以在其中指定键值对的顺序。这个 bson.D 对象可以用于 MongoDB 的排序、投影等操作,例如:
// 按照 age 降序排序并只返回 name 和 age 字段
collection.Find(bson.D{{"name", 1}, {"age", -1}}).Project(bson.D{{"name", 1}, {"age", 1}})
序列化和反序列化 bson:
// 将 bson.M 对象序列化为字节数组
data, err := bson.Marshal(doc)
// 将字节数组反序列化为 bson.M 对象
var result bson.M
err := bson.Unmarshal(data, &result)
这里使用 bson.Marshal() 函数将 bson.M 对象序列化为字节数组,然后使用 bson.Unmarshal() 函数将字节数组反序列化为 bson.M 对象。这个方法可以用于 MongoDB Go 驱动程序中的数据交换和存储操作。
猜你喜欢
- 2024-10-03 Spring Boot API 如何获得 JSON 数据
- 2024-10-03 大白话 golang 教程-20-使用 RPC 远程调用
- 2024-10-03 软件更新速递:Go发布1.15版本,这些新特性抢先看
- 2024-10-03 掌握 Postman 工具发送请求的简易教程
- 2024-10-03 python接口自动化-Json数据处理(python接口自动化流程)
- 2024-10-03 python接口自动化(八)--发送post请求的接口(详解)
- 2024-10-03 Flink 在唯品会的实践(唯品会 分析)
- 2024-10-03 web开发之-ajax的基本使用(处理json数据)
- 2024-10-03 Java POST JSON 数据处理异常 (code 160)): was expecting double-quote
- 2024-10-03 使用Postman发送POST请求的指南(postman如何发送post请求)
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)