文章目录
- Gin框架github地址 ⬅️点击此处
- 安装Gin及安装框架超时问题解决参考地址 ⬅️点击此处
- Mysql操作
- 建表
- 增加测试数据
- 代码实现
- 需要导的包
- 数据库连接函数及常量、数据传输结构体
- 业务代码:获取一条信息(GET请求)
- 业务代码:获取多条信息(GET请求)
- 业务代码:保存一条信息(POST请求)
- 业务代码:保存多条信息(POST请求)[使用mysql事务]
- 业务代码:上传文件并保存(POST请求)
在写代码之前,我们先了解一下Gin框架,Gin 是一个轻量级的 Go 语言 Web 框架,旨在提供一种简单、快速的方式来构建 Web 应用程序。它提供了一组简单的 API,可以让你轻松地处理 HTTP 请求、路由、模板渲染、中间件等功能。
Gin 的特点有:
- 简单易用:Gin 提供了一组简单的 API,使用起来非常方便。
- 高性能:Gin 在性能方面表现优秀,常常可以达到接近原生性能的水平。
- 支持中间件:Gin 支持使用中间件来扩展框架的功能,可以方便地实现认证、日志、跨域等功能。
- 支持多种模板引擎:Gin 可以使用多种模板引擎来渲染 HTML 模板,例如 Pongo2、Amber、Gin-Artemis 等。
使用 Gin 框架开发 Web 应用程序的一般流程如下:
- 安装 Gin 框架:使用
go get
命令安装 Gin 框架,或者在你的代码中导入github.com/gin-gonic/gin
包。 - 初始化 Gin 应用:使用
gin.Default()
函数初始化一个新的 Gin 应用,或者使用gin.New()
函数创建一个新的 Gin 应用并自定义配置。 - 定义路由和路由处理器:使用 Gin 应用的
GET
、POST
、`
Gin框架github地址 ⬅️点击此处
接下来我们来解决框架安装问题,使用官方的方式安装会超时
安装Gin及安装框架超时问题解决参考地址 ⬅️点击此处
除了gin之外还需要安装Mysql相关包~
go get -u github.com/go-sql-driver/mysql
Mysql操作
建表
DROP TABLE IF EXISTS `user_test`;
CREATE TABLE `user_test` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户主键id',
`name` varchar(50) NOT NULL COMMENT '用户姓名',
`phone` varchar(50) NOT NULL COMMENT '用户手机号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
增加测试数据
insert into user_test(`name`, `phone`) values ("Mary", "13111110000");
insert into user_test(`name`, `phone`) values ("Mr Li", "13989890000");
代码实现
需要导的包
import (
"database/sql"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
"log"
"net/http"
"strconv"
)
数据库连接函数及常量、数据传输结构体
// 数据库连接信息参数
const (
USERNAME = "root" //mysql账号用户名
PASSWORD = "rootroot" //mysql账号密码
NETWORK = "tcp" //连接方式
SERVER = "127.0.0.1" //ip
PORT = 3306 //port
DATABASE = "mysql" //库名
)
// 用于信息传输的结构体数据
type User_Test struct {
Name string `json:"name"` //起别名
Id int `json:"id"`
Phone string `json:"phone"`
}
// 数据库相关函数
func getDBConnect() (*sql.DB, error) {
conn := fmt.Sprintf("%s:%s@%s(%s:%d)/%s", USERNAME, PASSWORD, NETWORK, SERVER, PORT, DATABASE)
//获取DB连接驱动
db, err := sql.Open("mysql", conn)
if err != nil {
log.Println("do connect db error:", err.Error())
}
return db, err
}
业务代码:获取一条信息(GET请求)
func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
//(根据id获取用户)启动后的访问路径http://localhost:8080/getUserById?id=1
r.GET("/getUserById", func(c *gin.Context) {
// 接口参数获取
id := c.Query("id")
fmt.Println("ID:", id)
// 接口参数获取
params := c.Request.URL.Query()
fmt.Println("Params:", params)
//调用数据库函数
resultInfo := getOneInfoFromDB(id)
//接口返回数据组装
c.JSON(http.StatusOK, gin.H{
"user": resultInfo,
})
})
r.Run() // listen and serve on 0.0.0.0:8080
//r.Run("8888") // listen and serve on 0.0.0.0:8888
}
func getOneInfoFromDB(userId string) string {
if "" == userId || 0 == len(userId) {
//do nothing
return ""
}
// Connect to the database
db, err := getDBConnect()
if err != nil {
log.Println("do saveUser error:", err.Error())
}
//Passing parameters using placeholders
rows, err := db.Query("SELECT * FROM `user_test` where id = ?", userId)
if nil != err {
log.Println("do query error:", err)
return ""
}
//close
defer rows.Close()
var result string
for rows.Next() {
var user User_Test
//fill information
err = rows.Scan(&user.Id, &user.Name, &user.Phone)
if err != nil {
panic(err.Error())
}
//serialize information
marshal, err := json.Marshal(&user)
if nil != err {
log.Println("发生错误", err)
return ""
}
result = string(marshal)
}
defer db.Close()
// Make sure the connection is available
err = db.Ping()
if err != nil {
log.Println("do db.Ping() error:", err.Error())
}
return result
}
运行后浏览器访问:http://localhost:8080/getUserById?id=1
结果
{“user”:“{“name”:“Mary”,“id”:1,“phone”:“13111110000”}”}
业务代码:获取多条信息(GET请求)
func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
//(获取所有用户)启动后的访问路径http://localhost:8080/getMultipleUsers?limit=3
r.GET("/getMultipleUsers", func(c *gin.Context) {
// 获取参数
limit, err := strconv.Atoi(c.Query("limit"))
if err != nil {
// 如果参数不合法,返回错误
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid limit parameter"})
return
}
//调用数据库函数
resultInfo := getMultipleUserFromDB(limit)
//接口返回数据组装
c.JSON(http.StatusOK, gin.H{
"users": resultInfo,
})
})
r.Run() // listen and serve on 0.0.0.0:8080
//r.Run("8888") // listen and serve on 0.0.0.0:8888
}
// 获取多条用户信息
// limit:返回条数
func getMultipleUserFromDB(limit int) []User_Test {
resultUsers := make([]User_Test, 0, limit)
// Connect to the database
db, err := getDBConnect()
if err != nil {
log.Println("do saveUser error:", err.Error())
}
//Passing parameters using placeholders
rows, err := db.Query("SELECT * FROM `user_test` limit ?", limit)
if nil != err {
log.Println("do query error:", err)
return resultUsers
}
//close
defer rows.Close()
for rows.Next() {
var user User_Test
//fill information
err = rows.Scan(&user.Id, &user.Name, &user.Phone)
if err != nil {
panic(err.Error())
}
//append info slice
resultUsers = append(resultUsers, user)
}
defer db.Close()
// Make sure the connection is available
err = db.Ping()
if err != nil {
log.Println("do db.Ping() error:", err.Error())
}
return resultUsers
}
运行后浏览器访问http://localhost:8080/getMultipleUsers?limit=3,获取三条信息
结果
{“users”:[{“name”:“Mary”,“id”:1,“phone”:“13111110000”},{“name”:“Mr Li”,“id”:2,“phone”:“13989890000”},{“name”:“路人一”,“id”:3,“phone”:“13674749999”}]}
业务代码:保存一条信息(POST请求)
func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
//POST请求(保存用户),使用postman操作
r.POST("/saveUser", func(c *gin.Context) {
// 接口参数获取
name := c.PostForm("name")
phone := c.PostForm("phone")
user := User_Test{Name: name, Phone: phone}
// 接口参数获取
params := c.Request.URL.Query()
log.Println("Params:", params)
//调用数据库函数
resultFlag := saveUser(user)
if true == resultFlag {
//接口返回数据组装
c.JSON(http.StatusOK, gin.H{
"message": "Data saved successfully",
})
} else {
c.JSON(http.StatusExpectationFailed, gin.H{
"message": "Data saved failed!",
})
}
})
r.Run() // listen and serve on 0.0.0.0:8080
//r.Run("8888") // listen and serve on 0.0.0.0:8888
}
func saveUser(user User_Test) bool {
var flag bool = false
// Connect to the database
db, err := getDBConnect()
//操作成功返回true,保存出错打印错误返回false
_, err = db.Exec("INSERT INTO user_test (`name`, `phone`) VALUES (?, ?)", user.Name, user.Phone)
if err != nil {
log.Println("do saveUser error:", err.Error())
flag = false
}
flag = true
defer db.Close()
// Make sure the connection is available
err = db.Ping()
if err != nil {
log.Println("do db.Ping() error:", err.Error())
}
return flag
}
运行后使用postman操作
url:localhost:8080/saveUser
结果
查询数据库,发现数据已写入
业务代码:保存多条信息(POST请求)[使用mysql事务]
func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
//POST请求(保存多个用户),使用postman操作
r.POST("/saveMultipleUser", func(c *gin.Context) {
// 接口参数获取
recordsParam := c.PostForm("records")
log.Println(recordsParam)
// 定义一个结构体数组
var records []User_Test
//BindJSON方法是一个函数,用于解析 JSON(JavaScript 对象表示法)字符串并将其绑定到结构体中。
err := json.Unmarshal([]byte(recordsParam), &records)
if err != nil {
log.Println("json.Unmarshal error:", err)
c.JSON(http.StatusExpectationFailed, gin.H{
"message": "Data saved failed!",
})
return
}
//调用数据库函数
//如果有一个保存失败返回失败
resultFlag := saveUsers(records)
if resultFlag == false {
c.JSON(http.StatusExpectationFailed, gin.H{
"message": "Data saved failed!",
})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "Data saved successfully",
})
})
r.Run() // listen and serve on 0.0.0.0:8080
//r.Run("8888") // listen and serve on 0.0.0.0:8888
}
//保存多条用户,加入事务管理,全部保存成功提交事务,只要部分数据失败执行数据回滚
func saveUsers(users []User_Test) bool {
saveFlag := true
// Connect to the database
db, err := getDBConnect()
//开启数据库事务,用于保存失败后回滚数据
tx, err := db.Begin()
if err != nil {
// handle error
}
for _, user := range users {
//操作成功返回true,保存出错打印错误返回false
_, err = db.Exec("INSERT INTO user_test (`name`, `phone`) VALUES (?, ?)", user.Name, user.Phone)
if err != nil {
log.Println("do saveUser error:", err.Error())
saveFlag = false
}
}
//如果有数据保存失败,执行回滚
if false == saveFlag {
tx.Rollback()
return saveFlag
}
//全部保存成功后提交事务
err = tx.Commit()
if err != nil {
// handle error
}
return saveFlag
}
使用postman请求,参数:
records : [{“name”:“Lilei”,“phone”:“14133331111”},{“name”:“Mr Zhang”,“phone”:“15122223333”},{“name”:“路人二”,“phone”:“18113131111”}]
结果
{“message”: “Data saved successfully”}
数据库信息
业务代码:上传文件并保存(POST请求)
func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
//上传文件并保存
r.POST("/upload", func(c *gin.Context) {
// Get the uploaded file from the request
file, err := c.FormFile("file")
if err != nil {
c.AbortWithError(http.StatusBadRequest, err)
return
}
// Save the uploaded file to a specified directory
if err := c.SaveUploadedFile(file, "file/"+file.Filename); err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
// Return a success response
c.String(http.StatusOK, "File uploaded successfully")
})
r.Run() // listen and serve on 0.0.0.0:8080
//r.Run("8888") // listen and serve on 0.0.0.0:8888
}
使用postman上传文件
运行结果
File uploaded successfully