创建 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.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 方法,而且是用在特定的信息上。

$ 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" 一栏里。

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

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

$ curl -i -X PUT http://localhost:8080/people/3 -d '{ "FirstName": "Tom" }'

  显示如下

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

删除

  这次轮到删除功能了

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 方法测试一下

$ 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 这条记录已经删掉了。

[{"id": 2,"firstname": "Elvis","lastname": "Presley"},{"id": 3,"firstname": "Tom","lastname": "Sawyer"}]
 
 
 
 

作者:blackpiglet
链接:https://www.jianshu.com/p/443766f0e796
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

如何使用 Gin 和 Gorm 搭建一个简单的 API 服务 (二)的更多相关文章

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

    介绍   Go 语言最近十分火热,但对于新手来说,想立马上手全新的语法和各种各样的框架还是有点难度的.即使是基础学习也很有挺有挑战性.   在这篇文章中,我想用最少的代码写出一个可用的 API 服务. ...

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

    修改数据结构   基本的 API 已经定义好了,现在是个修改 Person 对象结构的好时机.只要修改 Person 结构体,数据库和 API 都会自动做出相应的修改.   我要做的是在 Person ...

  3. 超详细,新手都能看懂 !使用SpringBoot+Dubbo 搭建一个简单的分布式服务

    来自:JavaGuide Github 地址:https://github.com/Snailclimb/springboot-integration-examples 目录: 使用 SpringBo ...

  4. 使用 SpringBoot+Dubbo 搭建一个简单分布式服务

    实战之前,先来看几个重要的概念 开始实战之前,我们先来简单的了解一下这样几个概念:Dubbo.RPC.分布式.由于本文的目的是带大家使用SpringBoot+Dubbo 搭建一个简单的分布式服务,所以 ...

  5. 用nodejs搭建一个简单的服务器

    使用nodejs搭建一个简单的服务器 nodejs优点:性能高(读写文件) 数据操作能力强 官网:www.nodejs.org 验证是否安装成功:cmd命令行中输入node -v 如果显示版本号表示安 ...

  6. 初学Node(六)搭建一个简单的服务器

    搭建一个简单的服务器 通过下面的代码可以搭建一个简单的服务器: var http = require("http"); http.createServer(function(req ...

  7. 【netty】(2)---搭建一个简单服务器

    netty(2)---搭建一个简单服务器 说明:本篇博客是基于学习慕课网有关视频教学.效果:当用户访问:localhost:8088 后 服务器返回 "hello netty"; ...

  8. 使用gitblit搭建一个简单的局域网服务器

    使用gitblit搭建一个简单的局域网服务器 1.使用背景 现在很多使用github管理代码,但是github需要互联网的支持,而且私有的git库需要收费.有一些项目的代码不能外泄,所以,搭建一个局域 ...

  9. Golang学习-第二篇 搭建一个简单的Go Web服务器

    序言 由于本人一直从事Web服务器端的程序开发,所以在学习Golang也想从Web这里开始学起,如果对Golang还不太清楚怎么搭建环境的朋友们可以参考我的上一篇文章 Golang的简单介绍及Wind ...

随机推荐

  1. java+swing+mysql图书管理系统

    系统说明:本系统采用eclipse开发,IDEA,eclipse,myeclipse均可运行 界面采用swing实现 数据库:mysql,附sql代码,其余数据库可复制sql代码运行 数据库连接文件m ...

  2. 安装python3,配置pycharm

    1.下载最新版python3 首先去python官网下载python3的源码包,网址:https://www.python.org/ 进去之后点击导航栏的Downloads,也可以鼠标放到Downlo ...

  3. Java-Collection和Map

    创建博客的目的主要帮助自己记忆和复习日常学到和用到的知识:或有纰漏请大家斧正,非常感谢! 之前面试,被问过一个问题:List和Set的区别. 主要区别很明显了,两者都是数组形式存在的,继承了Colle ...

  4. Django循环创造div后,对各个div操作后触发事件,传递数据(Django九)

    前面我用for循环创建了div,每个div中有各自的数据以及同样的布局 效果图如下:部分代码如下: 现在,我希望在点击每个div里的发表按钮时,能在js里获取{{problem.pro_id}}以及{ ...

  5. Anaconda是个什么东东?

     2020/5/18 一.Anaconda 有什么用? 是一个安装.管理python相关包的软件,还自带python.Jupyter Notebook.Spyder,有管理包的conda工具,非常有用 ...

  6. P1295 [TJOI2011]书架 线段树优化dp,单调栈

    P1295 [TJOI2011]书架 本题思路比较好想(对我来说不是),但代码细节很多,奈何洛谷的题解只有思路,然后就是 没有丝毫解释的代码,让人看起来很头疼(~~ 尤其是像我这样的蒟蒻~~),所以便 ...

  7. 使用vue-cli(vue脚手架)快速搭建项目

    vue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目.这篇文章将会从实操的角度,介绍整个搭建的过程. 1. 避坑前言 其实这次使用vue-cli的 ...

  8. Java基础一篇过(一)反射

    一.反射是个啥 定义 : 在运行状态中动态获取的类的信息以及动态调用对象的方法,这种功能称为java语言的反射机制. 对于任意一个类,都能够知道这个类的所有属性和方法. 对于任意一个对象,都能够调用它 ...

  9. shiro 退出过滤器 logout ---退出清除HTTPSession数据

    重写LogouFilter类 import org.apache.shiro.web.filter.authc.LogoutFilter; public class ShiroLogoutFilter ...

  10. 适用于 deno 的多版本管理工具 dvm 发布

    不知不觉中,deno 已经默默的发布了 3 个版本了: 0.1.0 0.1.1 0.1.2 昨晚通宵做了一个 deno 多版本的管理工具: dvm. github 地址: https://github ...