» Go:使用Gin构建REST API » 2. 开发 » 2.4 路由设置

路由设置

修改 main.go,为 Book 添加 CRUD 路由:

添加 CRUD 操作

package main

import (
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"

	"literank.com/rest-books/model"
)

// 数据库实例
var db *gorm.DB

func main() {
	// 创建 Gin 路由设置器 router
	r := gin.Default()

	// 初始化数据库
	initDB()

	// 定义健康端点
	r.GET("/", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"status": "ok",
		})
	})
	r.GET("/books", getBooks)
	r.GET("/books/:id", getBook)
	r.POST("/books", createBook)
	r.PUT("/books/:id", updateBook)
	r.DELETE("/books/:id", deleteBook)

	r.Run(":8080")
}

// 初始化数据库
func initDB() {
	// 打开 SQLite 数据库
	var err error
	db, err = gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}

	// GORM 自动迁移
	db.AutoMigrate(&model.Book{})
}

// Get all books
func getBooks(c *gin.Context) {
	var books []model.Book
	db.Find(&books)

	c.JSON(http.StatusOK, books)
}

// Get single book
func getBook(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))
	var book model.Book
	if err := db.First(&book, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Record not found"})
		return
	}

	c.JSON(http.StatusOK, book)
}

// Create a new book
func createBook(c *gin.Context) {
	var reqBody model.Book
	if err := c.ShouldBindJSON(&reqBody); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	db.Create(&reqBody)

	c.JSON(http.StatusCreated, reqBody)
}

// Update an existing book
func updateBook(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))
	var book model.Book
	if err := db.First(&book, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Record not found"})
		return
	}

	var reqBody model.Book
	if err := c.ShouldBindJSON(&reqBody); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	db.Model(&book).Updates(&reqBody)

	c.JSON(http.StatusOK, book)
}

// Delete an existing book
func deleteBook(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))
	var book model.Book
	if err := db.First(&book, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Record not found"})
		return
	}

	db.Delete(&book)

	c.JSON(http.StatusNoContent, nil)
}

此刻,暂使用 SQLite1 数据库作演示使用。

GORM(gorm.io/gorm) 表示“Go ORM”,是一个流行的 Golang 对象关系映射库。它提供了一种与数据库交互的便捷方式。

curl 测试

创建一本新图书:

curl -X POST \
  http://localhost:8080/books \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Sample Book",
    "author": "John Doe",
    "published_at": "2023-01-01T00:00:00Z",
    "description": "A sample book description",
    "isbn": "1234567890",
    "total_pages": 200
}'

应如下响应:

{"id":1,"title":"Sample Book","author":"John Doe","published_at":"2023-01-01T00:00:00Z","description":"A sample book description","isbn":"1234567890","total_pages":200,"created_at":"2023-11-01T00:00:00Z","updated_at":"2023-11-01T00:00:00Z"}

根据 ID 获取一本图书:

curl -X GET http://localhost:8080/books/1

结果:

{
  "id": 1,
  "title": "Sample Book",
  "author": "John Doe",
  "published_at": "2023-01-01T00:00:00Z",
  "description": "A sample book description",
  "isbn": "1234567890",
  "total_pages": 200,
  "created_at": "2023-11-01T00:00:00Z",
  "updated_at": "2023-11-01T00:00:00Z"
}

列出所有图书:

curl -X GET http://localhost:8080/books

结果列表:

[
  {
    "id": 1,
    "title": "Sample Book",
    "author": "John Doe",
    "published_at": "2023-01-01T00:00:00Z",
    "description": "A sample book description",
    "isbn": "1234567890",
    "total_pages": 200,
    "created_at": "2024-02-23T22:19:55.263649+08:00",
    "updated_at": "2024-02-23T22:19:55.263649+08:00"
  },
  {
    "id": 2,
    "title": "Great Book",
    "author": "Rob Smith",
    "published_at": "2022-01-01T00:00:00Z",
    "description": "Another sample book description",
    "isbn": "8334567890",
    "total_pages": 3880,
    "created_at": "2024-02-23T22:25:55.067976+08:00",
    "updated_at": "2024-02-23T22:25:55.067976+08:00"
  }
]

更新一本已有的图书:

curl -X PUT \
  http://localhost:8080/books/1 \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Updated Book Title",
    "author": "Jane Smith"
}'

结果:

{
  "id": 1,
  "title": "Updated Book Title",
  "author": "Jane Smith",
  "published_at": "2023-01-01T00:00:00Z",
  "description": "A sample book description",
  "isbn": "1234567890",
  "total_pages": 200,
  "created_at": "2024-02-23T22:19:55.263649+08:00",
  "updated_at": "2024-02-23T22:32:55.881294+08:00"
}

删除一本已有的图书:

curl -X DELETE http://localhost:8080/books/1

服务端返回 code 204 以表示成功删除。

此刻 REST API 服务器已经初具雏形。不错!

Footnotes

  1. SQLite: https://www.sqlite.org/index.html

上页下页