使用GO(Gin)和Mongo的REST API
#api #go #休息 #mongodb

在此博客中,我们将构建一个带有两个端点的RESTFUL API服务器。示例项目将是图书馆中有关书籍的数据存储库。

这包括以下各节:

  1. 设计API端点。
  2. 创建一个代码文件夹。
  3. 使用QMGO连接到MongoDB
  4. 将处理者写给
    • 添加一本新书
    • 获取所有书籍
    • 获得一本特定的书
    • 删除特定书

先决条件:

  • GO 1.20或更高版本的安装。对于安装说明,visit
  • MongoDB 6.0或更高版本的安装。用于安装 说明,visit
  • 我们拥有的任何文本编辑器或IDE都可以正常工作。

设计API端点:

我们将建立一个API,可在图书馆中访问这些书籍。因此,我们需要提供端点,客户可以在图书馆中获取,添加或删除书籍。

这是我们在本教程中创建的终点。

/books

获取所有书籍的清单,返回为JSON。
帖子â添加以JSON发送的请求数据中的新书。

/books/:id

获取一本书的ID,将书籍数据返回为JSON。
补丁–通过其ID更新一本书,将书数据返回为JSON。
删除删除一本书的ID,将删除状态返回为JSON。

为我们的代码创建一个文件夹:

开始,我们将为我们要编写的代码创建一个项目。

使用命令提示符,为我们的代码创建一个名为书籍的文件夹。

$ mkdir books
$ cd books

创建一个可以管理依赖项的模块。

运行go mod init命令,为其代码所在的模块提供路径。

$ go mod init books
go: creating new go.mod: module books

此命令创建一个go.mod文件,其中我们添加的依赖项将被列出以进行跟踪。

代码

使用IDE/文本编辑器,创建一个名为main.go的文件。我们将在此文件中写入我们的GO代码。

在main.go中,在文件的顶部,添加以下包装声明和主函数,因为我们运行代码时将调用,因为独立程序(而不是库)始终在包装中。<<<<<<< br>

package main

func main() {

}

运行程序使用go run .

在包装声明之下,让我们开始编写连接到MongoDB的代码。

使用以下CMD

安装QMGO

go get github.com/gin-gonic/gin

导入“ github.com/qiniu/qmgo”软件包并声明可变的databasecollection并在主函数中初始化它们,以便以后可以使用它来对数据库中的数据进行CRUD操作。

var database *qmgo.Database
var collection *qmgo.Collection

func main() {

    // create new Client
    const databaseURI = "mongodb://localhost:27017"
    fmt.Println("Connecting to database", databaseURI)
    ctx := context.Background()
    connection, err := qmgo.NewClient(ctx, &qmgo.Config{Uri: databaseURI})

    database = connection.Database("test")    // creating Database connection
    collection = database.Collection("books") // get the collection
    defer func() {
        if err = connection.Close(ctx); err != nil {
            fmt.Println("Closing Connection to database", databaseURI)
            panic(err)
        }
    }()

}

现在,我们继续编写处理程序并配置应用程序以在主函数中收听HTTP端口(在我们的情况下8000)。

使用以下CMD

安装杜松子酒

go get github.com/gin-gonic/gin
并将其导入主文件

    router := gin.Default() // create router using gin

    // register routes
    router.POST("/books", CreateBook)

    fmt.Println("Service is up & running at localhost:8000")
    router.Run(":8000") // register router to port 8000

在这里,我们已经注册了一个帖子路由器,让我们继续创建创建书籍功能以处理创建请求

创建一个新的文件书。go,我们将编写用于处理请求的代码

创建书籍的请求和响应结构:

// form:"title" to map the JSON field name to the struct
// binding:"required" to enforce the value is required
type BookCreateUpdateRequest struct {
    Title  string `form:"title" binding:"required"`
    Author string `form:"author"`
}

// json:"id" to map the struct Name to its Json field name
type BookResponse struct {
    Id        primitive.ObjectID `json:"id"`
    Title     string             `json:"title"`
    Author    string             `json:"author"`
    CreatedAt time.Time          `json:"createdAt"`
    UpdatedAt time.Time          `json:"updatedAt"`
}

创建数据库模型结构:

type Book struct {
    field.DefaultField `bson:"inline"`
    Title              string `bson:"title" validate:"required"`
    Author             string `bson:"author"`
}

让我们创建createBookMethod来处理书籍创建请求。

func CreateBook(ctx *gin.Context) {
    var newBook BookCreateUpdateRequest

    // to bind the received JSON to BookRequest to strip the unnecessary fields.
    if err := ctx.ShouldBind(&newBook); err != nil {
        ctx.JSON(http.StatusBadRequest, "Invalid Request")
        return
    }

    // setting data to book model struct
    book := Book{
        Title:  newBook.Title,
        Author: newBook.Author,
    }
    _, err := collection.InsertOne(ctx, &book) //Inserting the Book Data to database

    // to send error response if any error occurs
    if err != nil {
        ctx.JSON(http.StatusInternalServerError, "Something went wrong, Try again after sometime")
        return
    }

    // to send success response on completion
    ctx.JSON(http.StatusCreated, GetBooksResponse(book))
}

func GetBooksResponse(book Book) (bookResponse BookResponse) {
    // setting response for book
    bookResponse = BookResponse{
        Id:        book.DefaultField.Id,
        Title:     book.Title,
        Author:    book.Author,
        CreatedAt: book.CreateAt,
        UpdatedAt: book.UpdateAt,
    }
    return
}

在上面的代码中,我们使用getBookssponse方法来设置要发送的响应(我们也将其用于其他API响应)。

以下是用于获取,列表,更新和删除的处理程序。

获取书籍详细信息API:

func GetBook(ctx *gin.Context) {

    // to get and convert the received path variable to  desired type
    bookId, err := primitive.ObjectIDFromHex(ctx.Param("bookId"))
    if err != nil {
        ctx.JSON(http.StatusBadRequest, "Invalid Request")
        return
    }

    //Getting the Book Data from database
    var book Book
    err = collection.Find(ctx, bson.M{"_id": bookId}).One(&book)

    // to send error response if any error occurs
    if err != nil {
        ctx.JSON(http.StatusNotFound, "Book Not Found")
        return
    }

    // to send success response on completion
    ctx.JSON(http.StatusOK, GetBooksResponse(book))
}

在上面的代码中,bson.M{"_id": bookId}用于通过ID查找这本书,并用于将Mongo数据绑定到书籍变量

更新一本书API:

func UpdateBook(ctx *gin.Context) {

    // to get and convert the received path variable to  desired type
    bookId, err := primitive.ObjectIDFromHex(ctx.Param("bookId"))
    if err != nil {
        ctx.JSON(http.StatusBadRequest, "Invalid Book ID")
        return
    }

    var newBook BookCreateUpdateRequest

    // to bind the received JSON to BookRequest to strip the unnecessary fields.
    if err := ctx.ShouldBind(&newBook); err != nil {
        ctx.JSON(http.StatusBadRequest, "Invalid Request")
        return
    }

    //Getting the Book Data from database
    var book Book
    err = collection.Find(ctx, bson.M{"_id": bookId}).One(&book)

    // to send error response if any error occurs
    if err != nil {
        ctx.JSON(http.StatusNotFound, "Book Not Found")
        return
    }

    // set the updated value in the book
    book.Author = newBook.Author
    book.Title = newBook.Title

    // update in database
    err = collection.ReplaceOne(ctx, bson.M{"_id": bookId}, &book)
    if err != nil {
        ctx.JSON(http.StatusInternalServerError, "Something went wrong, Try again after sometime")
        return
    }

    // to send success response on completion
    ctx.JSON(http.StatusOK, GetBooksResponse(book))
}

在上面的代码块中,collection.ReplaceOne用于基于条件替换现有文档。

删除书处理程序:

func DeleteBook(ctx *gin.Context) {

    // to get and convert the received path variable to  desired type
    bookId, err := primitive.ObjectIDFromHex(ctx.Param("bookId"))
    if err != nil {
        ctx.JSON(http.StatusBadRequest, "Invalid Request")
        return
    }

    //Getting the Book Data from database
    var book Book
    err = collection.Find(ctx, bson.M{"_id": bookId}).One(&book)

    // to send error response if any error occurs
    if err != nil {
        ctx.JSON(http.StatusNotFound, "Book Not Found")
        return
    }

    // Deleting the book
    err = collection.RemoveId(ctx, bookId)

    // to send error response if any error occurs
    if err != nil {
        ctx.JSON(http.StatusInternalServerError, "Something went wrong, Try again after sometime")
        return
    }

    // to send success response on completion
    ctx.JSON(http.StatusOK, true)
}

在上面的代码块中,collection.RemoveId用于根据提供的ID删除特定数据。

书籍清单处理程序

func GetBooks(ctx *gin.Context) {

    //Getting the Book Data to database
    var books []BookListResponse
    err := collection.Find(ctx, bson.M{}).All(&books)

    // to send error response if any error occurs
    if err != nil {
        fmt.Println(err)
        ctx.JSON(http.StatusInternalServerError, "Something went wrong, Try again after sometime")
        return
    }

    // to send success response on completion
    ctx.JSON(http.StatusOK, books)
}

在列表处理程序中,我们使用了booklistresponse,用于限制从数据库中读取的值,因为书籍和书名在列表API中就足够了。以下是BookListresponse类型。

type BookListResponse struct {
    Id    primitive.ObjectID `json:"id" bson:"_id"` // bson to map mongo _id to id
    Title string             `json:"title"`
}

在这里,bson:"_id"用于将mongo _id映射到响应中的id属性。

现在已经创建了所有处理程序,让我们在路由器中注册处理程序。Go通过在路由器声明后添加以下代码块。

    router.GET("/books", GetBooks)
    router.GET("/books/:bookId", GetBook)
    router.PATCH("/books/:bookId", UpdateBook)
    router.DELETE("/books/:bookId", DeleteBook)

恭喜!!!使用Mongo和GO在图书馆中用于书籍的CRUD REST API已成功完成。

您将能够在github repo中找到源代码:

GitHub logo Deeshath / books

使用GO和Mongo的书籍休息API

Books

Books REST API using go and mongo

Pre requisites:

  • An installation of Go 1.20 or later. For installation instructions, visit.
  • MongoDB 6.0或更高版本的安装。对于安装结构,visit

要启动thr rest api服务器使用CMD go run .