原生数据库使用
导入模块:go get -u github.com/go-sql-driver/mysql
安装 mysql 数据库
安装数据库可能遇到的问题:(网上的方法基本可以解决)
ERROR 1045 (28000): Access denied for user ‘-root’@‘localhost’ (using password: YES)
ERROR 2003 (HY000): Can’t connect to MySQL server on ‘localhost’ (10061)可视化数据库操作
// 导包内容
package main
import (
"database/sql" // 导入sql包处理数据库操作
"fmt" // 导入fmt包进行格式化输出和错误输出
"github.com/gin-gonic/gin" // 导入gin包快速构建REST API
_ "github.com/go-sql-driver/mysql" // 导入MySQL驱动
"net/http" // 导入http包处理HTTP请求
)
注意别漏了:_ “github.com/go-sql-driver/mysql” // 导入MySQL驱动
var sqlDb *sql.DB // 声明一个sql.DB指针,用于后续的数据库操作
var sqlResponse SqlResponse // sqlResponse是全局的用于封装http返回的结构体
/** 请求结构体 和 响应结构体 */
// SqlUser结构体映射数据库中的user表
type SqlUser struct {
Name string `json:"name"` // 用户名
Age int `json:"age"` // 年龄
Address string `json:"address"` // 地址
}
// SqlResponse结构体用于封装http响应数据
type SqlResponse struct {
Code int `json:"code"` // 响应状态码
Message string `json:"message"` // 响应消息
Data interface{} `json:"data"` // 响应数据
}
// init函数用于初始化数据库
func init() {
// MySQL连接字符串
sqlStr := "root:123456@tcp(127.0.0.1:3306)/testdb?charset=utf8&parseTime=true&loc=Local"
var err error
// 打开MySQL连接
sqlDb, err = sql.Open("mysql", sqlStr)
if err != nil {
// 如果连接出错,则输出错误并返回
fmt.Println("数据库打开出现了问题:", err)
return
}
// 测试与数据库的连接是否存活
err = sqlDb.Ping()
if err != nil {
fmt.Println("数据库打开出现了问题:", err)
return
}
}
// 主函数
func main() {
r := gin.Default()
r.POST("/sql/insert", insertData)
r.GET("/sql/read", readData)
r.GET("/sql/readAll", readAllData)
r.PUT("/sql/update", updateData)
r.DELETE("/sql/del", delData)
r.Run(":9090")
}
// insertData函数处理插入数据的请求
func insertData(context *gin.Context) {
var u SqlUser
// 绑定请求中的JSON数据到u结构体
err := context.Bind(&u)
if err != nil {
// 如果绑定出错,设置响应结构体并返回JSON响应
sqlResponse.Code = http.StatusBadRequest
sqlResponse.Message = "参数错误"
sqlResponse.Data = "error"
context.JSON(http.StatusOK, sqlResponse)
return
}
// 定义插入SQL语句
sqlStr := "insert into user(name, age, address) values (?,?,?)"
// 执行插入操作
ret, err := sqlDb.Exec(sqlStr, u.Name, u.Age, u.Address)
if err != nil {
// 如果插入出错,设置响应结构体并返回JSON响应
fmt.Println(err)
sqlResponse.Code = http.StatusBadRequest
sqlResponse.Message = "写入失败"
sqlResponse.Data = "error"
context.JSON(http.StatusOK, sqlResponse)
return
}
// 插入成功,设置响应结构体
sqlResponse.Code = http.StatusOK
sqlResponse.Message = "写入成功"
sqlResponse.Data = "OK"
// 返回JSON响应
context.JSON(http.StatusOK, sqlResponse)
// 打印插入的ID
fmt.Println(ret.LastInsertId())
}
// readData函数处理读取数据的请求:单条数据
func readData(context *gin.Context) {
name := context.Query("name") // 从查询参数获取name
// 定义查询SQL语句
sqlStr := "select age,address from user where name=?"
var u SqlUser
// 执行查询,并扫描结果到u结构体
err := sqlDb.QueryRow(sqlStr, name).Scan(&u.Age, &u.Address)
if err != nil {
// 如果查询出错,设置响应结构体并返回JSON响应
fmt.Println(err)
sqlResponse.Code = http.StatusBadRequest
sqlResponse.Message = "读取失败"
sqlResponse.Data = "error"
context.JSON(http.StatusOK, sqlResponse)
return
}
// 查询成功,填充姓名,并设置响应结构体
u.Name = name
sqlResponse.Code = http.StatusOK
sqlResponse.Message = "读取成功"
sqlResponse.Data = u
// 返回JSON响应
context.JSON(http.StatusOK, sqlResponse)
}
func readAllData(context *gin.Context) {
// 从Http请求中获取地址参数(address)
address := context.Query("address")
// 定义SQL查询语句,根据特定地址(address)查询与之匹配的所有用户名称(name)和用户年龄(age)
sqlStr := "select name, age from user where address=?"
// 使用预定义的sqlDb对象执行刚刚定义的SQL查询语句
rows, err := sqlDb.Query(sqlStr, address)
// 如果在执行SQL查询语句过程中出现错误,将错误信息打印到控制台,并向HTTP响应中写入相应的错误信息,然后退出当前函数
if err != nil {
fmt.Println(err)
sqlResponse.Code = http.StatusBadRequest
sqlResponse.Message = "读取失败"
sqlResponse.Data = "error"
context.JSON(http.StatusOK, sqlResponse)
return
}
// 定时关闭数据库连接
defer rows.Close()
// 定义一个空切片,用来存储所有查询到的用户数据
resUser := make([]SqlUser, 0)
// 遍历数据库查询结果集rows,提取所有的数据并添加到之前定义的用于存储用户数据的切片中
for rows.Next() {
var userTemp SqlUser
// 将从结果集中获取到的每一行数据相应的字段(name, age)提取出来,赋值给用户结构体(userTemp)对应的字段
rows.Scan(&userTemp.Name, &userTemp.Age)
// 将地址字段值设置为查询参数
userTemp.Address = address
// 将该用户结构体添加到用户切片中
resUser = append(resUser, userTemp)
}
// 设置HTTP响应的状态码、消息和数据内容,然后将其写入到HTTP响应中。这里写入的数据内容就是查询到的所有用户数据
sqlResponse.Code = http.StatusOK
sqlResponse.Message = "读取成功"
sqlResponse.Data = resUser
context.JSON(http.StatusOK, sqlResponse)
}
func updateData(context *gin.Context) {
// 定义一个SqlUser类型的变量u,用于存储请求中的用户数据
var u SqlUser
// 定义一个整型变量count,用于存储数据库查询返回的计数结果
var count int
// 使用context.Bind()方法从HTTP请求体中提取数据并绑定到变量u中
err := context.Bind(&u)
// 如果在数据绑定过程中发生错误,则向客户端发送参数错误的响应
if err != nil {
sqlResponse.Code = http.StatusBadRequest
sqlResponse.Message = "参数错误"
sqlResponse.Data = "error"
context.JSON(http.StatusOK, sqlResponse)
return
}
// 定义SQL查询字符串,用于检查具有特定名称的用户是否存在于数据库中
sqlStr := "select count(*) from user where name=?"
// 执行SQL查询,将查询结果(即用户的数量)存储于变量count中
err = sqlDb.QueryRow(sqlStr, u.Name).Scan(&count)
// 如果查询结果显示用户数量为0或查询时发生错误,则向客户端发送数据不存在的响应
if count <= 0 || err != nil {
sqlResponse.Code = http.StatusBadRequest
sqlResponse.Message = "更新的数据不存在"
sqlResponse.Data = "error"
context.JSON(http.StatusOK, sqlResponse)
return
}
// 定义SQL更新字符串,用于更新用户的年龄(age)和地址(address)
upStr := "update user set age=?, address=? where name=?"
// 执行SQL更新操作
ret, err := sqlDb.Exec(upStr, u.Age, u.Address, u.Name)
// 如果在执行更新操作时发生错误,则向客户端发送更新失败的响应
if err != nil {
fmt.Println(err)
sqlResponse.Code = http.StatusBadRequest
sqlResponse.Message = "更新失败"
sqlResponse.Data = "error"
context.JSON(http.StatusOK, sqlResponse)
return
}
// 如果更新操作成功,向客户端发送更新成功的响应
sqlResponse.Code = http.StatusOK
sqlResponse.Message = "更新成功"
sqlResponse.Data = "OK"
context.JSON(http.StatusOK, sqlResponse)
// 打印到控制台SQL操作返回的结果,这通常用于调试
// 注意:这里的LastInsertId()在更新操作中可能不会返回有意义的值,需要注意其适用场景
fmt.Println(ret.LastInsertId())
}
func delData(context *gin.Context) {
// 从HTTP请求的查询参数中获取需要删除的用户的名称
name := context.Query("name")
// 定义一个整型变量count,用于存储数据库查询返回的计数结果
var count int
// 定义SQL查询字符串,用于检查具有特定名称的用户是否存在于数据库中
sqlStr := "select count(*) from user where name=?"
// 执行SQL查询,将查询结果(即用户的数量)存储于变量count中
err := sqlDb.QueryRow(sqlStr, name).Scan(&count)
// 如果查询结果显示用户数量为0或查询时发生错误,则向客户端发送数据不存在的响应
if count <= 0 || err != nil {
sqlResponse.Code = http.StatusBadRequest
sqlResponse.Message = "删除的数据不存在"
sqlResponse.Data = "error"
context.JSON(http.StatusOK, sqlResponse)
return
}
// 定义SQL删除字符串,用于从数据库中删除具有特定名称的用户
delStr := "delete from user where name=?"
// 执行SQL删除操作
ret, err := sqlDb.Exec(delStr, name)
// 如果在执行删除操作时发生错误,则向客户端发送删除失败的响应
if err != nil {
sqlResponse.Code = http.StatusBadRequest
sqlResponse.Message = "删除的数据不存在"
sqlResponse.Data = "error"
context.JSON(http.StatusOK, sqlResponse)
return
}
// 如果删除成功,向客户端发送删除成功的响应
sqlResponse.Code = http.StatusOK
sqlResponse.Message = "删除成功"
sqlResponse.Data = "OK"
context.JSON(http.StatusOK, sqlResponse)
// 打印到控制台SQL操作返回的结果,这通常用于调试
// 注意:这里的LastInsertId()在删除操作中可能不会返回有意义的值,因为它更适用于插入操作
fmt.Println(ret.LastInsertId())
}
xorm框架
package main
import (
"fmt"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql" // 导入MySQL驱动
"github.com/go-xorm/xorm"
"net/http"
"time"
)
var x *xorm.Engine
var xormResponse XormResponse
type Stu struct {
Id int64 `xorm:"pk autoincr" json:"id"`
StuNum string `xorm:"unique" json:"stu_num"`
Name string `json:"name"`
Age int `json:"age"`
Created time.Time `xorm:"created" json:"created"`
Updated time.Time `xorm:"updated" json:"updated"`
}
type XormResponse struct {
Code int `json:"code"` // 响应状态码
Message string `json:"message"` // 响应消息
Data interface{} `json:"data"` // 响应数据
}
func init() {
sqlStr := "root:123456@tcp(127.0.0.1:3306)/xorm?charset=utf8&parseTime=true&loc=Local"
var err error
x, err = xorm.NewEngine("mysql", sqlStr)
if err != nil {
fmt.Println("数据库连接失败", err)
return
}
err = x.Sync(new(Stu))
if err != nil {
fmt.Println("数据库同步错误", err)
return
}
fmt.Println("数据库初始化成功", err)
}
func main() {
r := gin.Default()
r.POST("/xorm/insert", insertData)
r.GET("/xorm/read", readData)
r.GET("/xorm/mulread", mulReadData)
r.PUT("/xorm/update", xormUpdateData)
r.DELETE("/xorm/del", delData)
r.Run(":9090")
}
func insertData(context *gin.Context) {
var s Stu
err := context.Bind(&s)
if err != nil {
xormResponse.Code = http.StatusBadRequest
xormResponse.Message = "参数错误"
xormResponse.Data = "error"
context.JSON(http.StatusOK, xormResponse)
return
}
affected, err := x.Insert(s)
if affected <= 0 || err != nil {
xormResponse.Code = http.StatusBadRequest
xormResponse.Message = "写入失败"
xormResponse.Data = "error"
context.JSON(http.StatusOK, xormResponse)
return
}
xormResponse.Code = http.StatusOK
xormResponse.Message = "写入成功"
xormResponse.Data = "OK"
context.JSON(http.StatusOK, xormResponse)
}
func readData(context *gin.Context) {
stuNum := context.Query("stu_num")
var stus []Stu
err := x.Where("stu_num=?", stuNum).Find(&stus)
if err != nil {
xormResponse.Code = http.StatusBadRequest
xormResponse.Message = "查询错误"
xormResponse.Data = "error"
context.JSON(http.StatusOK, xormResponse)
return
}
xormResponse.Code = http.StatusOK
xormResponse.Message = "查询成功"
xormResponse.Data = stus
context.JSON(http.StatusOK, xormResponse)
}
func mulReadData(context *gin.Context) {
name := context.Query("name")
var stus []Stu
err := x.Where("name=?", name).And("age>20").Limit(10, 0).Asc("age").Find(&stus)
if err != nil {
xormResponse.Code = http.StatusBadRequest
xormResponse.Message = "查询错误"
xormResponse.Data = "error"
context.JSON(http.StatusOK, xormResponse)
return
}
xormResponse.Code = http.StatusOK
xormResponse.Message = "查询成功"
xormResponse.Data = stus
context.JSON(http.StatusOK, xormResponse)
}
func xormUpdateData(context *gin.Context) {
var s Stu
err := context.Bind(&s)
if err != nil {
xormResponse.Code = http.StatusBadRequest
xormResponse.Message = "参数错误"
xormResponse.Data = "error"
context.JSON(http.StatusOK, xormResponse)
return
}
var stus []Stu
err = x.Where("stu_num=?", s.StuNum).Find(&stus)
if err != nil || len(stus) <= 0 {
xormResponse.Code = http.StatusBadRequest
xormResponse.Message = "数据不存在"
xormResponse.Data = "error"
context.JSON(http.StatusOK, xormResponse)
return
}
affected, err := x.Where("stu_num=?", s.StuNum).Update(&Stu{Name: s.Name, Age: s.Age})
if err != nil || affected <= 0 {
xormResponse.Code = http.StatusBadRequest
xormResponse.Message = "修改失败"
xormResponse.Data = "error"
context.JSON(http.StatusOK, xormResponse)
return
}
xormResponse.Code = http.StatusBadRequest
xormResponse.Message = "修改成功"
xormResponse.Data = "OK"
context.JSON(http.StatusOK, xormResponse)
}
func delData(context *gin.Context) {
stuNum := context.Query("stu_num")
var stus []Stu
err := x.Where("name=?", stuNum).Find(&stus)
if err != nil {
xormResponse.Code = http.StatusBadRequest
xormResponse.Message = "没有此条数据"
xormResponse.Data = "error"
context.JSON(http.StatusOK, xormResponse)
return
}
affected, err := x.Where("stu_num=?", stuNum).Delete(&Stu{})
if err != nil || affected <= 0 {
xormResponse.Code = http.StatusBadRequest
xormResponse.Message = "删除失败"
xormResponse.Data = "error"
context.JSON(http.StatusOK, xormResponse)
return
}
xormResponse.Code = http.StatusBadRequest
xormResponse.Message = "删除成功"
xormResponse.Data = "OK"
context.JSON(http.StatusOK, xormResponse)
}
gorm框架
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"net/http"
"time"
)
type Product struct {
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
Number string `gorm:"unique" json:"number"`
Category string `gorm:"type:varchar(256);not null" json:"category"`
Name string `gorm:"type:varchar(20);not null" json:"name"`
MadeIn string `gorm:"type:varchar(128);not null" json:"madeIn"`
ProductionTime time.Time `json:"production_time"`
}
type GormResponse struct {
Code int `json:"code"` // 响应状态码
Message string `json:"message"` // 响应消息
Data interface{} `json:"data"` // 响应数据
}
var gormResponse GormResponse
var gormDB *gorm.DB
func init() {
var err error
sqlStr := "root:123456@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=true&loc=Local"
gormDB, err = gorm.Open(mysql.Open(sqlStr), &gorm.Config{})
if err != nil {
fmt.Println("数据库连接失败", err)
return
}
}
func main() {
r := gin.Default()
r.POST("/gorm/insert", insetData)
r.GET("/gorm/read", readData)
r.GET("/gorm/readAll", readAllData)
r.PUT("/gorm/update", updateData)
r.DELETE("/gorm/del", delData)
r.Run(":9090")
}
func errorTouch(context *gin.Context) {
defer func() {
err := recover()
if err != nil {
gormResponse.Code = http.StatusBadRequest
gormResponse.Message = "错误"
gormResponse.Data = err
context.JSON(http.StatusOK, gormResponse)
}
}()
}
func insetData(context *gin.Context) {
errorTouch(context)
var p Product
err := context.Bind(&p)
if err != nil {
gormResponse.Code = http.StatusBadRequest
gormResponse.Message = "参数错误"
gormResponse.Data = err
context.JSON(http.StatusOK, gormResponse)
return
}
tx := gormDB.Create(&p)
if tx.RowsAffected <= 0 {
gormResponse.Code = http.StatusBadRequest
gormResponse.Message = "写入失败"
gormResponse.Data = "error"
context.JSON(http.StatusBadRequest, gormResponse)
return
}
gormResponse.Code = http.StatusOK
gormResponse.Message = "写入成功"
gormResponse.Data = "ok"
context.JSON(http.StatusOK, gormResponse)
}
func readData(context *gin.Context) {
errorTouch(context)
number := context.Query("number")
product := Product{}
tx := gormDB.Where("number=?", number).First(&product)
if tx.Error != nil {
gormResponse.Code = http.StatusBadRequest
gormResponse.Message = "查询错误"
gormResponse.Data = tx.Error
context.JSON(http.StatusOK, gormResponse)
return
}
gormResponse.Code = http.StatusBadRequest
gormResponse.Message = "查询成功"
gormResponse.Data = product
context.JSON(http.StatusOK, gormResponse)
}
func readAllData(context *gin.Context) {
category := context.Query("category")
products := make([]Product, 10)
tx := gormDB.Where("category=?", category).Find(&products).Limit(10)
if tx.Error != nil {
gormResponse.Code = http.StatusBadRequest
gormResponse.Message = "查询错误"
gormResponse.Data = tx.Error
context.JSON(http.StatusOK, gormResponse)
return
}
gormResponse.Code = http.StatusOK
gormResponse.Message = "查询成功"
gormResponse.Data = products
context.JSON(http.StatusOK, gormResponse)
}
func updateData(context *gin.Context) {
errorTouch(context)
var p Product
err := context.Bind(&p)
if err != nil {
gormResponse.Code = http.StatusBadRequest
gormResponse.Message = "参数错误"
gormResponse.Data = err
context.JSON(http.StatusOK, gormResponse)
return
}
var count int64
gormDB.Model(&Product{}).Where("number=?", p.Number).Count(&count)
if count <= 0 {
gormResponse.Code = http.StatusBadRequest
gormResponse.Message = "数据不存在"
gormResponse.Data = "error"
context.JSON(http.StatusOK, gormResponse)
return
}
tx := gormDB.Model(&Product{}).Where("number=?", p.Number).Updates(&p)
if tx.RowsAffected <= 0 {
gormResponse.Code = http.StatusBadRequest
gormResponse.Message = "写入失败"
gormResponse.Data = "error"
context.JSON(http.StatusOK, gormResponse)
return
}
gormResponse.Code = http.StatusOK
gormResponse.Message = "更新成功"
gormResponse.Data = "ok"
context.JSON(http.StatusOK, gormResponse)
}
func delData(context *gin.Context) {
errorTouch(context)
number := context.Query("number")
var count int64
gormDB.Model(&Product{}).Where("number=?", number).Count(&count)
if count <= 0 {
gormResponse.Code = http.StatusBadRequest
gormResponse.Message = "数据不存在"
gormResponse.Data = "error"
context.JSON(http.StatusOK, gormResponse)
return
}
tx := gormDB.Where("number=?", number).Delete(&Product{})
if tx.RowsAffected <= 0 {
gormResponse.Code = http.StatusBadRequest
gormResponse.Message = "删除失败"
gormResponse.Data = "error"
context.JSON(http.StatusOK, gormResponse)
return
}
gormResponse.Code = http.StatusOK
gormResponse.Message = "删除成功"
gormResponse.Data = "ok"
context.JSON(http.StatusOK, gormResponse)
}