ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、视频、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
### GoWeb开发实战】Gin框架\_数据库 # 基于`database/sql`的CURD操作 对于Gin本身,并没有对数据库的操作,本文实现的是,通过http访问程序,然后操作mysql数据库库。 ## 一、查询 我们以之前讲解mysql时所使用的数据表为例: ![gin_db1](http://image.chaindesk.cn/gin_db1.png/mark) 接下来,我们就查询这张表,并将查询的结果以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) ![gin_yunxing42](http://image.chaindesk.cn/gin_yunxing42.png/mark) ## 二、插入数据 我们可以设计一个方法用于向数据库中添加数据: ~~~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页面来访问: ![gin_yunxing43](http://image.chaindesk.cn/gin_yunxing43.png/mark) 也可以查询数据库,查看数据是否插入成功: ![gin_db2](http://image.chaindesk.cn/gin_db2.png/mark) ## 三、修改数据 添加一个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请求: ![gin_yunxing44](https://www.chaindesk.cn/Users/ruby/Documents/ChainDesk/Gin%E6%A1%86%E6%9E%B6%E5%BC%80%E5%8F%91%E4%B8%8E%E5%AE%9E%E6%88%98/http://image.chaindesk.cn/gin_yunxing44.png/mark) 查看数据库: ![gin_db3](https://www.chaindesk.cn/Users/ruby/Documents/ChainDesk/Gin%E6%A1%86%E6%9E%B6%E5%BC%80%E5%8F%91%E4%B8%8E%E5%AE%9E%E6%88%98/http://image.chaindesk.cn/gin_db3.png/mark) ## 四、删除数据 我们可以根据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访问: ![gin_yunxing45](http://image.chaindesk.cn/gin_yunxing45.png/mark) 查看数据库,是否真正的删除,我们发现id为10的数据已经没有了: ![gin_db4](http://image.chaindesk.cn/gin_db4.png/mark)