### GoWeb开发实战】Gin框架\_数据库
# 基于`database/sql`的CURD操作
对于Gin本身,并没有对数据库的操作,本文实现的是,通过http访问程序,然后操作mysql数据库库。
## 一、查询
我们以之前讲解mysql时所使用的数据表为例:

接下来,我们就查询这张表,并将查询的结果以json的形式,返回给客户端。
示例代码:
~~~go
//定义User类型结构
type User struct {
Id int `json:"id"`
Username string `json:"username"`
Password string `json:"password"`
}
//定义一个getALL函数用于回去全部的信息
func getAll() (users []User, err error) {
//1.操作数据库
db, _ := sql.Open("mysql", "root:hanru1314@tcp(127.0.0.1:3306)/mytest?charset=utf8")
//错误检查
if err != nil {
log.Fatal(err.Error())
}
//推迟数据库连接的关闭
defer db.Close()
//2.查询
rows, err := db.Query("SELECT id, username, password FROM user_info")
if err != nil {
log.Fatal(err.Error())
}
for rows.Next() {
var user User
//遍历表中所有行的信息
rows.Scan(&user.Id, &user.Username, &user.Password)
//将user添加到users中
users = append(users, user)
}
//最后关闭连接
defer rows.Close()
return
}
~~~
首先定义对应数据表的结构体,然后就是操作数据库进行查询,这些是之前已经学习过的了,如果不会mysql操作,请移步:[GoWeb开发实战(Beego框架实现项目)](http://www.chaindesk.cn/witbook/17)
接下来,我们写web访问:
~~~go
//创建一个路由Handler
router := gin.Default()
//get方法的查询
router.GET("/user", func(c *gin.Context) {
users, err := getAll()
if err != nil {
log.Fatal(err)
}
//H is a shortcut for map[string]interface{}
c.JSON(http.StatusOK, gin.H{
"result": users,
"count": len(users),
})
})
router.Run(":8080")
~~~
启动项目后,通过浏览器访问:[http://127.0.0.1:8080/user](http://127.0.0.1:8080/user)

## 二、插入数据
我们可以设计一个方法用于向数据库中添加数据:
~~~go
//插入数据
func add(user User) (Id int, err error) {
//1.操作数据库
db, _ := sql.Open("mysql", "root:hanru1314@tcp(127.0.0.1:3306)/mytest?charset=utf8")
//错误检查
if err != nil {
log.Fatal(err.Error())
}
//推迟数据库连接的关闭
defer db.Close()
stmt, err := db.Prepare("INSERT INTO user_info(username, password) VALUES (?, ?)")
if err != nil {
return
}
//执行插入操作
rs, err := stmt.Exec(user.Username, user.Password)
if err != nil {
return
}
//返回插入的id
id, err := rs.LastInsertId()
if err != nil {
log.Fatalln(err)
}
//将id类型转换
Id = int(id)
defer stmt.Close()
return
}
~~~
然后我们添加一个POST的路由,当通过post请求的时候,我们向数据库中插入数据:
~~~go
//利用post方法新增数据
router.POST("/add", func(c *gin.Context) {
var u User
err := c.Bind(&u)
if err != nil {
log.Fatal(err)
}
Id, err := add(u)
fmt.Print("id=", Id)
c.JSON(http.StatusOK, gin.H{
"message": fmt.Sprintf("%s 插入成功", u.Username),
})
})
~~~
因为我们需要绑定struct类型,所以还需要修改之前的User:
~~~go
//定义User类型结构
type User struct {
Id int `json:"id" form:"id"`
Username string `json:"username" form:"username"`
Password string `json:"password" form:"password"`
}
~~~
然后使用postman,模拟Post请求,当然,你也可以使用终端通过curl命令,或者直接写个HTML页面来访问:

也可以查询数据库,查看数据是否插入成功:

## 三、修改数据
添加一个update方法用于修改数据,我们实现的是根据id修改其他的字段:
~~~go
//修改数据
func update(user User) (rowsAffected int64, err error) {
//1.操作数据库
db, _ := sql.Open("mysql", "root:hanru1314@tcp(127.0.0.1:3306)/mytest?charset=utf8")
//错误检查
if err != nil {
log.Fatal(err.Error())
}
//推迟数据库连接的关闭
defer db.Close()
stmt, err := db.Prepare("UPDATE user_info SET username=?, password=? WHERE id=?")
if err != nil {
return
}
//执行修改操作
rs, err := stmt.Exec(user.Username, user.Password,user.Id)
if err != nil {
return
}
//返回插入的id
rowsAffected,err =rs.RowsAffected()
if err != nil {
log.Fatalln(err)
}
defer stmt.Close()
return
}
~~~
然后在main中新添加一个路由:
~~~go
//利用put方法修改数据
router.PUT("/update", func(c *gin.Context) {
var u User
err := c.Bind(&u)
if err != nil {
log.Fatal(err)
}
num, err := update(u)
fmt.Print("num=", num)
c.JSON(http.StatusOK, gin.H{
"message": fmt.Sprintf("修改id: %d 成功", u.Id),
})
})
~~~
然后重新程序后,用postman模拟post请求:

查看数据库:

## 四、删除数据
我们可以根据Id删除一条数据,删除刚刚修改的id为10的数据,先添加一个delete方法:
~~~go
//通过id删除
func del(id int) (rows int, err error) {
//1.操作数据库
db, _ := sql.Open("mysql", "root:hanru1314@tcp(127.0.0.1:3306)/mytest?charset=utf8")
//错误检查
if err != nil {
log.Fatal(err.Error())
}
//推迟数据库连接的关闭
defer db.Close()
stmt, err := db.Prepare("DELETE FROM user_info WHERE id=?")
if err != nil {
log.Fatalln(err)
}
rs, err := stmt.Exec(id)
if err != nil {
log.Fatalln(err)
}
//删除的行数
row, err := rs.RowsAffected()
if err != nil {
log.Fatalln(err)
}
defer stmt.Close()
rows = int(row)
return
}
~~~
然后再main中注册一个路由:
~~~go
//利用DELETE请求方法通过id删除
router.DELETE("/delete/:id", func(c *gin.Context) {
id := c.Param("id")
Id, err := strconv.Atoi(id)
if err != nil {
log.Fatalln(err)
}
rows, err := del(Id)
if err != nil {
log.Fatalln(err)
}
fmt.Println("delete rows ", rows)
c.JSON(http.StatusOK, gin.H{
"message": fmt.Sprintf("Successfully deleted user: %s", id),
})
})
~~~
然后重新运行项目,使用postman模拟delete访问:

查看数据库,是否真正的删除,我们发现id为10的数据已经没有了:
