如何使用 Gin 和 Gorm 搭建一个简单的 API 服务 (二)

早过忘川 提交于 2020-08-09 14:40:01

创建 API

  我们之前已经跑过 Gin 框架的代码,现在是时候加些功能进去了。

读取全部信息

  我们先从"增删改查"中的"查"入手,查询我们之前添加的信息。我接下来要删除几行代码,并把 Gin 的框架代码加回来。

package main

import (
        "fmt"
        "github.com/gin-gonic/gin" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/sqlite" ) var db *gorm.DB var err error type Person struct { ID uint `json:"id”` FirstName string `json:"firstname”` LastName string `json:"lastname”` } func main() { // NOTE: See we’re using = to assign the global var // instead of := which would assign it only in this function db, err = gorm.Open("sqlite3", "./gorm.db") if err != nil { fmt.Println(err) } defer db.Close() db.AutoMigrate(&Person{}) r := gin.Default() r.GET("g/", GetProjects) r.Run("g:8080") } func GetProjects(c *gin.Context) { var people []Person if err := db.Find(&people).Error; err != nil { c.AbortWithStatus(404) fmt.Println(err) } else { c.JSON(200, people) } } 

  那么运行程序,并在浏览器中访问 http://localhost:8080,你应该看到:

[{“id”: 1,”firstname”: “John”,”lastname”: “Doe”}] 

  喔,几行代码我们就可以拿到 API 服务器的响应了,而且大部分代码都是用来错误处理的。

读取特定信息

  好,为了把 API 接口写的更符合 REST 规范,我们加入查询特定信息的借口

package main

import (
    "fmt"
    "github.com/gin-gonic/gin" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/sqlite" ) var db *gorm.DB var err error type Person struct { ID uint `json:"id”` FirstName string `json:"firstname”` LastName string `json:"lastname”` } func main() { // NOTE: See we’re using = to assign the global var // instead of := which would assign it only in this function db, err = gorm.Open("sqlite3", "./gorm.db") if err != nil { fmt.Println(err) } defer db.Close() db.AutoMigrate(&Person{}) r := gin.Default() r.GET("g/", GetProjects) r.GET("/people/:id", GetPerson) r.Run("g:8080") } func GetProjects(c *gin.Context) { var people []Person if err := db.Find(&people).Error; err != nil { c.AbortWithStatus(404) fmt.Println(err) } else { c.JSON(200, people) } } func GetPerson(c *gin.Context) { id := c.Params.ByName("id") var person Person if err := db.Where("id = ?", id).First(&person).Error; err != nil { c.AbortWithStatus(404) fmt.Println(err) } else { c.JSON(200, person) } } 

  现在运行程序,但请注意,如果要访问全部信息,你需要访问的地址变成了 http://localhost:8080/people/ ,如果 在 URL 的末尾加入了 ID,你就会得到特定的信息 http://localhost:8080/people/1

{"id": 1, "firstname": "John", "lastname": "Doe"} 

添加信息

  只有一条记录是看不大出来查询全部信息和查询单条信息的区别的,所以咱们来把添加信息的功能加上吧。

package main

import (
    "fmt"
    "github.com/gin-gonic/gin" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/sqlite" ) var db *gorm.DB var err error type Person struct { ID uint `json:"id”` FirstName string `json:"firstname”` LastName string `json:"lastname”` } func main() { // NOTE: See we’re using = to assign the global var // instead of := which would assign it only in this function db, err = gorm.Open("sqlite3", "./gorm.db") if err != nil { fmt.Println(err) } defer db.Close() db.AutoMigrate(&Person{}) r := gin.Default() r.GET("g/", GetProjects) r.GET("/people/:id", GetPerson) r.POST("/people", CreatePerson) r.Run("g:8080") } func GetProjects(c *gin.Context) { var people []Person if err := db.Find(&people).Error; err != nil { c.AbortWithStatus(404) fmt.Println(err) } else { c.JSON(200, people) } } func GetPerson(c *gin.Context) { id := c.Params.ByName("id") var person Person if err := db.Where("id = ?", id).First(&person).Error; err != nil { c.AbortWithStatus(404) fmt.Println(err) } else { c.JSON(200, person) } } func CreatePerson(c *gin.Context) { var person Person c.BindJSON(&person) db.Create(&person) c.JSON(200, person) } 

  接下来让我们从终端运行 curl 命令测试一下新加的功能是不是可用,当然还是先要把程序运行起来。
  在终端运行:

$ curl -i -X POST http://localhost:8080/people -d '{ "FirstName": "Elvis", "LastName": "Presley"}' 

  应该会看到成功的响应消息:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8 Date: Sat, 03 Dec 2016 00:14:06 GMT Content-Length: 50 {"id":2,"firstname":"Elvis","lastname":"Presley"} 

  现在我们访问一下查询全部信息的接口,http://localhost:8080/people/

[{"id": 1,"firstname": "John","lastname": "Doe"},{"id": 2,"firstname": "Elvis","lastname": "Presley"}] 

  太棒啦,代码没问题。这回我们只发送 Person 结构体的部分信息,看看程序会如何处理。

$ curl -i -X POST http://localhost:8080/people -d '{ "FirstName": "Madison"}' 

  刷新一下浏览器,发现只添加了我们发送的信息。

[{"id": 1,"firstname": "John","lastname": "Doe"},{"id": 2,"firstname": "Elvis","lastname": "Presley"},{"id": 3,"firstname": "Madison","lastname": ""}] 

  这就是 Gin 如何工作的了,留意一下 c.BindJSON(&person) 这行,它会自动匹配请求消息中的数据信息。
  虽然请求消息里可能缺某些信息,就比如刚才那个例子,而且大小写不匹配也没有关系,Gin 的容错性非常高。非常简单!

更新信息

  我们不能把 Madison 这条记录没有姓氏啊,是时候加入更新功能了。

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/sqlite" ) var db *gorm.DB var err error type Person struct { ID uint `json:"id"` FirstName string `json:"firstname"` LastName string `json:"lastname"` } func main() { // NOTE: See we're using = to assign the global var // instead of := which would assign it only in this function db, err = gorm.Open("sqlite3", "./gorm.db") if err != nil { fmt.Println(err) } defer db.Close() db.AutoMigrate(&Person{}) r := gin.Default() r.GET("g/", GetProjects) r.GET("/people/:id", GetPerson) r.POST("/people", CreatePerson) r.PUT("/people/:id", UpdatePerson) r.Run("g:8080") } func GetProjects(c *gin.Context) { var people []Person if err := db.Find(&people).Error; err != nil { c.AbortWithStatus(404) fmt.Println(err) } else { c.JSON(200, people) } } func GetPerson(c *gin.Context) { id := c.Params.ByName("id") var person Person if err := db.Where("id = ?", id).First(&person).Error; err != nil { c.AbortWithStatus(404) fmt.Println(err) } else { c.JSON(200, person) } } func CreatePerson(c *gin.Context) { var person Person c.BindJSON(&person) db.Create(&person) c.JSON(200, person) } func UpdatePerson(c *gin.Context) { var person Person id := c.Params.
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!