前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何使用 Gin 和 Gorm 搭建一个简单的 API 服务 (二)

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

作者头像
用户2443625
发布2018-08-23 11:46:28
1.5K0
发布2018-08-23 11:46:28
举报
文章被收录于专栏:blackpigletblackpiglet

gin-gonic

  这是系列文章的第二篇。下面是另外两篇的链接:

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

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

创建 API

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

读取全部信息

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

代码语言:javascript
复制
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,你应该看到:

代码语言:javascript
复制
[{“id”: 1,”firstname”: “John”,”lastname”: “Doe”}]

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

读取特定信息

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

代码语言:javascript
复制
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

代码语言:javascript
复制
{"id": 1, "firstname": "John", "lastname": "Doe"}
添加信息

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

代码语言:javascript
复制
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 命令测试一下新加的功能是不是可用,当然还是先要把程序运行起来。

  在终端运行:

代码语言:javascript
复制
$ curl -i -X POST http://localhost:8080/people -d '{ "FirstName": "Elvis", "LastName": "Presley"}'

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

代码语言:javascript
复制
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/

代码语言:javascript
复制
[{"id": 1,"firstname": "John","lastname": "Doe"},{"id": 2,"firstname": "Elvis","lastname": "Presley"}]

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

代码语言:javascript
复制
$ curl -i -X POST http://localhost:8080/people -d '{ "FirstName": "Madison"}'

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

代码语言:javascript
复制
[{"id": 1,"firstname": "John","lastname": "Doe"},{"id": 2,"firstname": "Elvis","lastname": "Presley"},{"id": 3,"firstname": "Madison","lastname": ""}]

  这就是 Gin 如何工作的了,留意一下 c.BindJSON(&person) 这行,它会自动匹配请求消息中的数据信息。

  虽然请求消息里可能缺某些信息,就比如刚才那个例子,而且大小写不匹配也没有关系,Gin 的容错性非常高。非常简单!

更新信息

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

代码语言:javascript
复制
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.ByName("id")
    if err := db.Where("id = ?", id).First(&person).Error; err != nil {
        c.AbortWithStatus(404)
        fmt.Println(err)
    }
    c.BindJSON(&person)
    db.Save(&person)
    c.JSON(200, person)
}

  这次我们用类似的 curl 命令 进行测试,但不同的是用 PUT 方法,而且是用在特定的信息上。

代码语言:javascript
复制
$ curl -i -X PUT http://localhost:8080/people/3 -d '{ "FirstName": "Madison", "LastName":"Sawyer" }'
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Sat, 03 Dec 2016 00:25:35 GMT
Content-Length: 51
{"id":3,"firstname":"Madison","lastname":"Sawyer"}

  当然更新浏览器后,我们就可以看见 "sawyer" 添加到了 "LastName" 一栏里。

代码语言:javascript
复制
[{"id": 1,"firstname": "John","lastname": "Doe"},{"id": 2,"firstname": "Elvis","lastname": "Presley"},{"id": 3,"firstname": "Madison","lastname": "Sawyer"}]

  这次我们只更新 "FirstName" 字段试试。

代码语言:javascript
复制
$ curl -i -X PUT http://localhost:8080/people/3 -d '{ "FirstName": "Tom" }'

  显示如下

代码语言:javascript
复制
[{"id": 1,"firstname": "John","lastname": "Doe"},{"id": 2,"firstname": "Elvis","lastname": "Presley"},{"id": 3,"firstname": "Tom","lastname": "Sawyer"}]
删除

  这次轮到删除功能了

代码语言:javascript
复制
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.DELETE("/people/:id", DeletePerson)

    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.ByName("id")
    if err := db.Where("id = ?", id).First(&person).Error; err != nil {
        c.AbortWithStatus(404)
        fmt.Println(err)
    }
    c.BindJSON(&person)
    db.Save(&person)
    c.JSON(200, person)
}

func DeletePerson(c *gin.Context) {
    id := c.Params.ByName("id")
    var person Person
    d := db.Where("id = ?", id).Delete(&person)
    fmt.Println(d)
    c.JSON(200, gin.H{"id #" + id: "deleted"})
}

  我们用 curl 的 Delete 方法测试一下

代码语言:javascript
复制
$ curl -i -X DELETE http://localhost:8080/people/1

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Sat, 03 Dec 2016 00:32:40 GMT
Content-Length: 20

{"id #1":"deleted"}

  刷新浏览器,John Doe 这条记录已经删掉了。

代码语言:javascript
复制
[{"id": 2,"firstname": "Elvis","lastname": "Presley"},{"id": 3,"firstname": "Tom","lastname": "Sawyer"}]
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.03.14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建 API
    • 读取全部信息
      • 读取特定信息
        • 添加信息
          • 更新信息
            • 删除
            相关产品与服务
            API 网关
            腾讯云 API 网关(API Gateway)是腾讯云推出的一种 API 托管服务,能提供 API 的完整生命周期管理,包括创建、维护、发布、运行、下线等。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档