创建 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. dom:文档对象模型,提供的api去操作页面上的元素

    dom对象通过html标签转义成了文档操作对象

  2. [算法与数据结构]使用Java泛型实现栈

    ###题解 1 实现内部类node 2 维护top为头节点的链表 3 操作 操作1:push() 操作2: pop() 操作3: isEmpty() ###代码 package Exam; class ...

  3. Java 基础知识面试题(2020 最新版)

    Java面试总结汇总,整理了包括Java基础知识,集合容器,并发编程,JVM,常用开源框架Spring,MyBatis,数据库,中间件等,包含了作为一个Java工程师在面试中需要用到或者可能用到的绝大 ...

  4. ribbon源码(6) Server

    Server 代表一个服务器信息. 内部有服务器地址(host).服务器端口(port).服务器dc(zone).是否存活标志(isAliveFlag).请求协议(scheme).是否可以提供服务(r ...

  5. java虚拟机配置

    -XXSurvivorRatio 设置两个survivor和eden的比,8表示两个survivor:eden:2:8.survivor的比例影响新生代向老年代移动的数度.survivor比例越小,新 ...

  6. Class对象、反射、动态代理

    Class对象是所有类的根源,Object是所有对象的根源. 编译后的新类会产生一个Class对象,保存在同名的.class文件中.每个类都有一个Class对象,它包含了所有的与类有关的信息.所有的C ...

  7. HTML自学第一篇

    教程来自W3CSchool 因为笔者有过开发经验 本篇只是个人对HTML自学的笔记,可能不适合用于给他人理解和学习 什么是 HTML HTML 指的是超文本标记语言 (Hyper Text Marku ...

  8. Spring学习(十一)--Spring MVC

    1.MVC模式 (1)视图 通过视图展示应用数据    向应用数据提供更新动作   向控制器提交用户动作   运行控制器选择不同视图 (2)模型提供 封装应用数据状态  响应数据状态查询  提供应用功 ...

  9. mybatis基础使用

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis .20 ...

  10. selenium3介绍

    1.  简介 Selenium是用于测试 Web应用程序用户界面 (UI)的常用框架.它是一款用于运行端到端功能测试的超强工具.您可以使用多个编程语言编写测试,并且 Selenium能够在一个或多个浏 ...