直接用代码显示每句代码什么意思都用注释写明
package main
// 引入gin
import "github.com/gin-gonic/gin"
// main函数
func main() {
// 创建一个默认路由引擎
r := gin.Default()
// 配置路由
r.GET("/", func(context *gin.Context) {
context.String(200, "值:%v", "你好")
})
// 启动一个web服务
r.Run() // 可以写入想要的端口号,r.Run(":8888")
}
如果跑了代码,每次修改都需要重新跑一次
gin官方并没有提供热加载的功能,就需要借助第三方工具
本人使用的是fresh,也有其他的热加载工具
安装方法(在终端直接输入即可):
go get github.com/pilu/fresh
使用方法直接在终端输入fresh即可
Query()可以获取到传过来的值
DefaultQuery()可以获取到传过来的值,如果没值可以输入默认值
// 如何获取get传值
r.GET("/get", func(context *gin.Context) {
// 无默认值
username := context.Query("username")
age := context.Query("age")
// 如果没有传值,有默认值
page := context.DefaultQuery("page", "1")
context.JSON(http.StatusOK, gin.H{
"username": username,
"age": age,
"page": page,
})
})
在浏览器输入http://localhost:8080/get?username=你好&age=18&page=10
就可以得到{“age”:“18”,“page”:“10”,“username”:“你好”}
如果不传page也可以有默认值http://localhost:8080/get?username=你好&age=18
得到{“age”:“18”,“page”:“1”,“username”:“你好”}
// 如何过去post传值from
r.POST("/post", func(context *gin.Context) {
// 无默认值
username := context.PostForm("username")
password := context.PostForm("password")
// 有默认值
age := context.DefaultPostForm("age", "18")
context.JSON(http.StatusOK, gin.H{
"username": username,
"password": password,
"age": age,
})
})
可以用前端form标签试试,也可以使用Gin的html模版语法,我直接使用apifox
两个差别不大,下面我放一个post请求的图片
type UserInfo struct {
Username string `json:"username" form:"username"`
Password string `json:"password" form:"password"`
}
func main() {
// 创建一个默认路由引擎
r := gin.Default()
// GET结构体请求
r.GET("/getUser", func(context *gin.Context) {
user := &UserInfo{}
err := context.ShouldBind(&user)
if err == nil {
context.JSON(http.StatusOK, user)
} else {
context.JSON(http.StatusBadRequest, gin.H{
"err": err.Error(),
})
}
})
// POST结构体请求
r.POST("/postUser", func(context *gin.Context) {
user := &UserInfo{}
err := context.ShouldBind(&user)
if err == nil {
context.JSON(http.StatusOK, user)
} else {
context.JSON(http.StatusBadRequest, gin.H{
"err": err.Error(),
})
}
})
// 启动一个web服务
r.Run()
}
// GET动态路由
r.GET("/list/:cid", func(context *gin.Context) {
cid := context.Param("cid")
context.String(http.StatusOK, "%v", cid)
})
官方文档路由组
官方直接写在main函数中,我的例子就抽离出来
// 传入创建的路由引擎,传入的类型到main看
func Api(r *gin.Engine) {
r.GET("/api/userList", func(context *gin.Context) {
context.String(http.StatusOK, "这是用户列表接口")
})
}
// 记得要引入对应的文件
import (
"day1/routers"
)
// 在main函数的创建路由引擎后面调用Api函数
routers.Api(r)
// 路由中间件函数
func routeMiddleware(c *gin.Context) {
fmt.Println("我是路由中间件")
// 去执行请求剩余处理程序
c.Next()
fmt.Println("我是路由中间件2")
}
func main() {
r := gin.Default()
r.GET("/", routeMiddleware, func(context *gin.Context) {
fmt.Println("我是首页")
context.String(http.StatusOK, "值:%v", "你好")
})
}
这是打印出来的顺序
2. 全局中间件
和路由中间件其实是差不多的,只要在main函数中加入Use(),就可以在任何请求的情况下都会使用到全局中间件
// 全局中间件
func middleware(c *gin.Context) {
fmt.Println("我是全局中间件")
// 去执行请求剩余处理程序
c.Next()
fmt.Println("我是全局中间件2")
}
func main() {
r := gin.Default()
r.Use(middleware)
r.GET("/", func(context *gin.Context) {
fmt.Println("我是首页")
context.String(http.StatusOK, "值:%v", "你好")
})
}
// 就会打印出 我是全局中间件 我是首页 我是全局中间件2
任何请求都可以有多个中间件(路由、全局) 也可以将中间件函数单独拿出来,创建一个文件夹(middlewares),在文件夹创建一个go文件,里面上中间件的函数,在需要的地方引入就可以了具体可以看文档
package middlewares
import (
"fmt"
"github.com/gin-gonic/gin"
"time"
)
func InitMiddleware(c *gin.Context) {
// 获取时间
fmt.Println(time.Now())
// 获取请求地址
fmt.Println(c.Request.URL)
// 传值
c.Set("username", "我有多么帅")
}
将中间件引入对应的路由中
package routers
import (
"day1/controllers/admin"
"day1/middlewares"
"github.com/gin-gonic/gin"
)
// Api 传入创建的路由引擎,传入的类型到main看
func Api(r *gin.Engine) {
apiRouters := r.Group("/api", middlewares.InitMiddleware)
{
apiRouters.GET("/userList", admin.UserControllers{}.Index)
}
}
// 记得到main函数中引入routers.Api(r)
路由中使用了控制器,就可以在控制器中使用中间件传过来的值
package admin
import (
"github.com/gin-gonic/gin"
"net/http"
)
type UserControllers struct {
}
func (con UserControllers) Index(c *gin.Context) {
// 获取中间件传来的值
username, _ := c.Get("username")
// 类型断言
v, ok := username.(string)
if ok {
c.String(http.StatusOK, "用户列表 " + v)
} else {
c.String(http.StatusOK, "用户列表 失败")
}
}
直接续中间件下面写的
func (con UserControllers) Upload(c *gin.Context) {
// 获取文件
file, err := c.FormFile("file")
// 获取文件保存路径 file.Filename获取文件名称
dst := path.Join("./static/upload", file.Filename)
// 判断是否获取成功
if err == nil {
// 获取文件保存路径 file.Filename获取文件名称
dst := path.Join("./static/upload", file.Filename)
// 将图片存到对应的目录中
c.SaveUploadedFile(file, dst)
}
c.JSON(http.StatusOK, gin.H{
"dst": dst,
})
}
单文件和多文件是一样的,获取多个文件即可。多文件上传还分相同名字上传以数组的形式循环遍历获取,不同名字上传直接对不同名字进行处理。
我这里使用的数据库是mysql,用了gorm工具,使用这个工具就可以不需要写sql语句了
import (
"fmt"
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// 结构体和数据库表字段一致,首字母大写
type User struct {
Id int
Name string
Age int
}
func main() {
// 连接数据库需要准备的东西
// root是数据库账号,xxxxx是数据库密码,item是连接对应的库
dsn := "root:xxxxxx@tcp(127.0.0.1:3306)/item?charset=utf8mb4"
// 连接数据库
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 对连接失败进行判断
if err != nil {
fmt.Println(err)
}
// 添加一条数据
user := &User{Id: 1, Name: "张三", Age: 2}
db.Create(&user)}
// 查找一条数据
userList := &User{}
db.Where("id=1").First(&userList)
}
持续更新中