上一篇介绍了Gin+Mysql简单的Restful风格的API,但代码放在一个文件中,还不属于restful风格,接下来将进行进一步的封装。

目录结构

☁  gin_restful2  tree
.
├── api
│ └── users.go
├── db
│ └── mysql.go
├── main.go
├── models
│ └── users.go
└── router.go

api文件夹存放我们的handler函数,用于逻辑处理,models文件夹用来存放我们的数据模型。

myql.go的包代码如下:

package db

import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"log"
) var SqlDB *sql.DB
func init() {
var err error
SqlDB, err = sql.Open("mysql", "root:password@tcp(127.0.0.1:3306)/test?charset=utf8mb4")
if err != nil {
log.Fatal(err.Error())
}
err = SqlDB.Ping()
if err != nil {
log.Fatal(err.Error())
}
}

因为我们需要在别的地方使用SqlDB这个变量,因此依照golang的习惯,变量名必须大写开头。

数据model封装

修改models文件夹下的users.go,把对应的Person结构及其方法移到这里:

package models
import (
"gin_restful2/db"
"log"
) type Person struct {
Id int `json:"id" form:"id"`
Name string `json:"name" form:"name"`
Telephone string `json:"telephone" form:"telephone"`
} //插入
func (person *Person) Create() int64 {
rs, err := db.SqlDB.Exec("INSERT into users (name, telephone) value (?,?)", person.Name, person.Telephone)
if err != nil{
log.Fatal(err)
}
id, err := rs.LastInsertId()
if err != nil{
log.Fatal(err)
}
return id
} //查询一条记录
func (p *Person) GetRow() (person Person, err error) {
person = Person{}
err = db.SqlDB.QueryRow("select id,name,telephone from users where id = ?", p.Id).Scan(&person.Id, &person.Name, &person.Telephone)
return
} //查询所有记录
func (person *Person) GetRows() (persons []Person, err error) {
rows, err := db.SqlDB.Query("select id,name,telephone from users")
for rows.Next(){
person := Person{}
err := rows.Scan(&person.Id, &person.Name, &person.Telephone)
if err != nil {
log.Fatal(err)
}
persons = append(persons, person)
}
rows.Close()
return
} //修改
func (person *Person) Update() int64{
rs, err := db.SqlDB.Exec("update users set telephone = ? where id = ?", person.Telephone, person.Id)
if err != nil {
log.Fatal(err)
}
rows, err := rs.RowsAffected()
if err != nil {
log.Fatal(err)
}
return rows
} //删除一条记录
func Delete(id int) int64 {
rs, err := db.SqlDB.Exec("delete from users where id = ?", id)
if err != nil {
log.Fatal()
}
rows, err := rs.RowsAffected()
if err != nil {
log.Fatal()
}
return rows
}

handler

然后把具体的handler函数封装到api包中,因为handler函数要操作数据库,所以会引用model包,api/users.go代码如下:

package api

import (
"github.com/gin-gonic/gin"
"net/http"
"fmt"
."gin_restful2/models"
"strconv"
) //index
func IndexUsers(c *gin.Context) {
c.String(http.StatusOK, "It works")
} //增加一条记录
func AddUsers(c *gin.Context) {
name := c.Request.FormValue("name")
telephone := c.Request.FormValue("telephone")
person := Person{
Name:name,
Telephone:telephone,
}
id := person.Create()
msg := fmt.Sprintf("insert successful %d", id)
c.JSON(http.StatusOK, gin.H{
"msg": msg,
})
} //获得一条记录
func GetOne(c *gin.Context) {
ids := c.Param("id")
id, _ := strconv.Atoi(ids)
p := Person{
Id:id,
}
rs, _ := p.GetRow()
c.JSON(http.StatusOK, gin.H{
"result": rs,
})
} //获得所有记录
func GetAll(c *gin.Context) {
p := Person{}
rs, _ := p.GetRows()
c.JSON(http.StatusOK, gin.H{
"list": rs,
})
} func UpdateUser(c *gin.Context) {
ids := c.Request.FormValue("id")
id, _ := strconv.Atoi(ids)
telephone := c.Request.FormValue("telephone")
person := Person{
Id:id,
Telephone:telephone,
}
row := person.Update()
msg := fmt.Sprintf("updated successful %d", row)
c.JSON(http.StatusOK, gin.H{
"msg": msg,
})
} //删除一条记录
func DelUser(c *gin.Context) {
ids := c.Request.FormValue("id")
id, _ := strconv.Atoi(ids)
row := Delete(id)
msg := fmt.Sprintf("delete successful %d", row)
c.JSON(http.StatusOK, gin.H{
"msg": msg,
})
}

路由

最后就是把路由抽离出来,修改router.go,我们在路由文件中封装路由函数

package main

import (
"github.com/gin-gonic/gin"
. "gin_restful2/api"
) func initRouter() *gin.Engine {
router := gin.Default()
router.GET("/", IndexUsers) //http://localhost:8806 //路由群组
users := router.Group("api/v1/users")
{
users.GET("", GetAll) //http://localhost:8806/api/v1/users
users.POST("/add", AddUsers) //http://localhost:8806/api/v1/users/add
users.GET("/get/:id", GetOne) //http://localhost:8806/api/v1/users/get/5
users.POST("/update", UpdateUser)
users.POST("/del", DelUser)
} return router
}

app入口

最后就是main函数的app入口,将路由导入,同时我们要在main函数结束的时候,关闭全局的数据库连接池:

main.go

package main

import (
"gin_restful2/db"
) func main() {
defer db.SqlDB.Close()
router := initRouter()
router.Run(":8806")
}

至此,我们就把简单程序进行了更好的组织。当然,golang的程序组织依包为基础,不拘泥,根据具体的应用场景可以组织。

此时运行项目,不能像之前简单的使用go run main.go,因为包main包含main.go和router.go的文件,因此需要运行go run *.go命令编译运行。如果是最终编译二进制项目,则运行go build -o app

Gin实战:Gin+Mysql简单的Restful风格的API(二)的更多相关文章

  1. Gin实战:Gin+Mysql简单的Restful风格的API

    我们已经了解了Golang的Gin框架.对于Webservice服务,restful风格几乎一统天下.Gin也天然的支持restful.下面就使用gin写一个简单的服务,麻雀虽小,五脏俱全.我们先以一 ...

  2. 使用webpy创建一个简单的restful风格的webservice应用

    下载:wget http://webpy.org/static/web.py-0.38.tar.gz解压并进入web.py-0.38文件夹安装:easy_install web.py 这是一个如何使用 ...

  3. PHP实现Restful风格的API

    Restful是一种设计风格而不是标准,比如一个接口原本是这样的: http://www1.qixoo.com/user/view/id/1表示获取id为1的用户信息,如果使用Restful风格,可以 ...

  4. [01] 浅谈RESTful风格的API

    1.什么是RESTful风格的API REST,即Representational State Transfer,可以理解为"(资源的)表现层状态转化". 在网络上,我们通过浏览器 ...

  5. Dubbo 03 Restful风格的API

    目录 Dubbo03 restful风格的API 根路径 协议 版本 用HTTP协议里的动词来实现资源的增删改查 用例 swagger(丝袜哥) OpenAPI 资源 编写API文档 整合Spring ...

  6. 测开大佬告诉你:如何5分钟快速创建restful风格的API接口-使用django restframework框架

    一.思考❓❔ 1.创建API接口难吗? 软件测试工程师: 只测过API接口, 从没创建过 应该需要掌握一门后端开发语言和后端开发框架吧!? 脑容量有限,想想就可怕 2.如何创建API接口呢? 使用Dj ...

  7. PHP实现Restful风格的API(转)

    Restful是一种设计风格而不是标准,比如一个接口原本是这样的: http://www1.qixoo.com/user/view/id/1表示获取id为1的用户信息,如果使用Restful风格,可以 ...

  8. PHP实现RESTful风格的API实例(三)

    接前一篇PHP实现RESTful风格的API实例(二) .htaccess :重写URL,使URL以 /restful/class/1 形式访问文件 Options +FollowSymlinks R ...

  9. PHP实现RESTful风格的API实例(二)

    接前一篇PHP实现RESTful风格的API实例(一) Response.php :包含一个Request类,即输出类.根据接收到的Content-Type,将Request类返回的数组拼接成对应的格 ...

随机推荐

  1. (转)可以一同使用 DISTINCT 和 COUNT 关键词,来计算非重复结果的数目。

    点击收看

  2. you need to be root to perform this command

    在linux 终端执行某条命令时 提示一下错误 you need to be root to perform this command 是提示要获取root权限 输入su 回车输入密码 即可解决 参考 ...

  3. python3.7使用models.ForeignKey时一定要传入实参on_delete=models.CASCADE

    models.ForeignKey 模型中最重要的部分——以及模型中唯一需要的部分——是它定义的数据库字段列表.字段由类属性指定.注意不要选择与模型API冲突的字段名称,如清除.保存或删除. from ...

  4. WP8.1StoreApp(WP8.1RT)---第三方启动

    8.1的协议和wp8是相互通用的 被启动: 相比较wp8而言,基本变化不大,但添加方式更直观了 1:打开Package.appxmanifest 2:切换到"声明"选项卡 3:左侧 ...

  5. Posix消息队列注意事项

    随内核的持续性 读总是返回最高优先级的最早消息. 当往一个空队列放置一个消息时,允许产生一个信号或启动一个线程. 可认为是一个消息链表 队列中每个消息具有 1.一个无符号整数优先级 2.消息的数据部分 ...

  6. python--变量,常量,用户交互

    1.变量 概念:把程序运行过程中产生的中间值保存在内存,方便后面使用 命名规范: 1.字母,数字,下划线组成 2.不能用数字开头,且不能用纯数字 3.不能用python关键字 4.不要用中文 5.要有 ...

  7. 【OCP题库-12c】最新CUUG OCP 071考试题库(69题)

    69.(31-1)choose the best answer: Evaluate the following query: SELECT INTERVAL '300' MONTH, INTERVAL ...

  8. 配置DNS服务器转发器

    1.(windows server 2008 r2)控制面板->管理工具->服务器管理器->DNS->服务器图标->属性 2.转发器->编辑 3.填写DNS并点击确 ...

  9. java从txt文档读写数据

    package com.abin.facade.ws.mail.function; import java.io.BufferedReader; import java.io.File; import ...

  10. PHP消息队列实现

    一个经典的消息队列就是这样的,主要是入队出队操作. shell脚本日志输出 学习地址:http://www.imooc.com/article/19111