E:\code\go\gin框架学习>go version
go version go1.20.3 windows/amd64
使用vscode进行go开发. 按ctrl+~ 弹出终端,进行设置
go env -w GOPROXY=https://goproxy.cn,direct
查看设置结果,设置成功
go env |findstr /i goproxy
set GOPROXY=https://goproxy.cn,direct
在项目目录下执行一下命令,生成go.mod文件
E:\code\go\gin框架学习>go mod init hellogin
go: creating new go.mod: module hellogin
go get -u github.com/gin-gonic/gin
package main
import (
"github.com/gin-gonic/gin"
)
func sayHello(c *gin.Context) {
c.JSON(200, gin.H{
"message": "hello gin",
})
}
func main() {
//返回一个默认的路由引擎
r := gin.Default()
//设置一个基础的get请求
r.GET("/hello", sayHello)
//运行gin框架
r.Run()
}
访问127.0.0.1:8080/hello就能看到一串JSON字符串。
package main
import (
"github.com/gin-gonic/gin"
)
func sayHello(c *gin.Context) {
data := gin.H{
"name": "zhangsan",
"age": "20",
}
c.JSON(200, data)
}
func main() {
//返回一个默认的路由引擎
r := gin.Default()
//设置一个基础的get请求
r.GET("/hello", sayHello)
//运行gin框架
r.Run()
}
package main
import (
"github.com/gin-gonic/gin"
)
func sayHello(c *gin.Context) {
// 这里定义了 值类型为interface的map数据类型
data := map[string]interface{}{
"name": "lisi",
"age": 30,
}
c.JSON(200, data)
}
func main() {
//返回一个默认的路由引擎
r := gin.Default()
//设置一个基础的get请求
r.GET("/hello", sayHello)
//运行gin框架
r.Run()
}
package main
import (
"github.com/gin-gonic/gin"
)
//字段全部改为大写
type student struct {
name string
age int
gender string
}
func sayHello(c *gin.Context) {
data := student{"wangwu", 20, "boy"}
c.JSON(200, data)
}
func main() {
//返回一个默认的路由引擎
r := gin.Default()
//设置一个基础的get请求
r.GET("/hello", sayHello)
//运行gin框架
r.Run()
}
此时在浏览器中返回的数据是空 {}结果。这是因为结果中的字段没有首字母大写。
package main
import (
"github.com/gin-gonic/gin"
)
type student struct {
Name string
Age int
Gender string
}
func sayHello(c *gin.Context) {
data := student{"wangwu", 20, "boy"}
c.JSON(200, data)
}
func main() {
//返回一个默认的路由引擎
r := gin.Default()
//设置一个基础的get请求
r.GET("/hello", sayHello)
//运行gin框架
r.Run()
}
此时返回结果正常。
{"Name":"wangwu","Age":20,"Gender":"boy"}
如果想要返回小写的类型名称,还是需要使用tag
package main
import (
"github.com/gin-gonic/gin"
)
type student struct {
Name string `json:"name"`
Age int `json:"age"`
Gender string `json:"gender"`
}
func sayHello(c *gin.Context) {
data := student{"wangwu", 20, "boy"}
c.JSON(200, data)
}
func main() {
//返回一个默认的路由引擎
r := gin.Default()
//设置一个基础的get请求
r.GET("/hello", sayHello)
//运行gin框架
r.Run()
}
http://127.0.0.1:8080/hello?name=zhangsan&age=20
获取查询参数中的name和age的值
package main
import (
"github.com/gin-gonic/gin"
)
func sayHello(c *gin.Context) {
getname := c.Query("name")
getage := c.Query("age")
data := gin.H{
"name": getname,
"age": getage,
}
c.JSON(200, data)
}
func main() {
//返回一个默认的路由引擎
r := gin.Default()
//设置一个基础的get请求
r.GET("/hello", sayHello)
//运行gin框架
r.Run()
}
如果没有查询到,定义一个默认的返回的结果
不传值
http://127.0.0.1:8080/hello?
或者没有对应的key值
http://127.0.0.1:8080/hello?name1=lisi
package main
import (
"github.com/gin-gonic/gin"
)
func sayHello(c *gin.Context) {
getname := c.DefaultQuery("name", "为获取到值")
getage := c.DefaultQuery("age", "为获取到值")
data := gin.H{
"name": getname,
"age": getage,
}
c.JSON(200, data)
}
func main() {
//返回一个默认的路由引擎
r := gin.Default()
//设置一个基础的get请求
r.GET("/hello", sayHello)
//运行gin框架
r.Run()
}
package main
import (
"github.com/gin-gonic/gin"
)
func sayHello(c *gin.Context) {
getusername := c.PostForm("username")
getpassword := c.PostForm("password")
data := gin.H{
"username": getusername,
"password": getpassword,
"age": 20,
}
c.JSON(200, data)
}
func main() {
//返回一个默认的路由引擎
r := gin.Default()
//设置一个基础的get请求
r.GET("/hello", sayHello)
r.POST("/hello", sayHello)
//运行gin框架
r.Run()
}
使用postman 模拟提交form表单数据
上边的postform函数只能获取 form格式提交过来的数据。如果不知道用户传递过来的body是什么样的数据类型(Content-Type).就可以使用此函数将数据和结构体对应上。
此函数会按照下边的顺序解析请求中的数据完成绑定:
1.如果是get请求,只使用Form绑定引擎
2.如果是post请求,默认是按照json格式绑定数据
这里就是使用json格式数据提交 username和password值,就可以绑定成功.
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type userinfo struct {
Username string
Password string
Age int
}
func sayHello(c *gin.Context) {
var uf userinfo
err := c.ShouldBind(&uf)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
} else {
data := gin.H{
"username": uf.Username,
"password": uf.Password,
}
c.JSON(200, data)
}
}
func main() {
//返回一个默认的路由引擎
r := gin.Default()
//设置一个基础的get请求
r.POST("/hello/", sayHello)
//运行gin框架
r.Run()
}
使用form格式进行提交,需要给结构体打tag.这样json和form格式就都可以进行绑定了
type userinfo struct {
Username string `form:"username"`
Password string `form:"password"`
Age int
}
为了稳定一般我们会把tag写全,保证不会出错
type userinfo struct {
Username string `form:"username" json:"username"`
Password string `form:"password" json:"password"`
Age int
}
package main
import (
"github.com/gin-gonic/gin"
)
func sayHello(c *gin.Context) {
//获取url中定义的变量
getusername := c.Param("username")
getage := c.Param("age")
data := gin.H{
"username": getusername,
"password": getage,
}
c.JSON(200, data)
}
func main() {
//返回一个默认的路由引擎
r := gin.Default()
//讲url中的值映射位一个变量,然后在函数中获取
r.GET("/hello/:username/:age", sayHello)
//运行gin框架
r.Run()
}
这些都是普通路由
r.GET()
r.POST()
在上边的方法中,r.get或者r.post来区分用户的请求。而r.any只要路径匹配,不论用户是什么请求方法都匹配
r.Any("/user", getuser)
r.NoRoute
package main
import (
"github.com/gin-gonic/gin"
)
func no_route(ctx *gin.Context) {
ctx.JSON(404, gin.H{
"message": "404没有配到相关路径",
})
}
func getuser(ctx *gin.Context) {
ctx.JSON(200, gin.H{
"user": "zhangsan",
"id": 3,
})
}
func main() {
var r = gin.Default()
r.Any("/user", getuser)
r.NoRoute(no_route)
r.Run()
}
package main
import (
"github.com/gin-gonic/gin"
)
func rootfunc(c *gin.Context) {
c.JSON(200, gin.H{
"message": "这是根路径",
})
}
func adduser(c *gin.Context) {
c.JSON(200, gin.H{
"message": "添加用户",
})
}
func deleteuser(c *gin.Context) {
c.JSON(200, gin.H{
"message": "删除用户",
})
}
func main() {
router := gin.Default()
router.GET("/", rootfunc)
r1 := router.Group("/user")
r1.Any("/add", adduser)
r1.Any("/delete", deleteuser)
router.Run()
}
定义: 其实在gin框架中 中间件就是一个普通的函数,是在用户的请求到达 请求处理函数之前经过的 “函数”
package main
import (
"github.com/gin-gonic/gin"
)
//设置一个中间件函数
func m1(c *gin.Context) {
c.JSON(200, gin.H{
"message": "我是m1中间件",
})
}
//普通函数
func rootfunc(c *gin.Context) {
c.JSON(200, gin.H{
"message": "这是根路径",
})
}
func adduser(c *gin.Context) {
c.JSON(200, gin.H{
"message": "添加用户",
})
}
func deleteuser(c *gin.Context) {
c.JSON(200, gin.H{
"message": "删除用户",
})
}
func main() {
router := gin.Default()
//没有配置中间件
router.GET("/", rootfunc)
r1 := router.Group("/user")
//配置使用中间件m1
r1.Any("/add", m1, adduser)
r1.Any("/delete", m1, deleteuser)
router.Run()
}
此时发现,/add和/delete 路由都使用了 中间件。而/路由 就没有使用
如果路由由很多,每个路由都需要手动配置中间件就很麻烦,这时候就用到了中间件的全局注册。
全局注册其实语法很简单,使用
路由实例.use(中间件函数1,中间件函数2,......)
实例如下:
func main() {
router := gin.Default()
//进行了全局注册
router.Use(m1)
//每个路由就不用在手动添加中间件函数了
router.GET("/", rootfunc)
r1 := router.Group("/user")
r1.Any("/add", adduser)
r1.Any("/delete", deleteuser)
router.Run()
}
此函数的作用是,阻止后续的所有中间件函数,路由函数执行
package main
import (
"github.com/gin-gonic/gin"
)
//中间函数1
func m1(c *gin.Context) {
//这里使用了abort函数
c.Abort()
c.JSON(200, gin.H{
"message": "我是m1中间件",
})
}
//中间函数2
func m2(c *gin.Context) {
c.JSON(200, gin.H{
"message": "我是m2中间件",
})
}
func rootfunc(c *gin.Context) {
c.JSON(200, gin.H{
"message": "这是根路径",
})
}
func adduser(c *gin.Context) {
c.JSON(200, gin.H{
"message": "添加用户",
})
}
func deleteuser(c *gin.Context) {
c.JSON(200, gin.H{
"message": "删除用户",
})
}
func main() {
router := gin.Default()
//全局注册两个中间件函数
router.Use(m1, m2)
router.GET("/", rootfunc)
r1 := router.Group("/user")
r1.Any("/add", adduser)
r1.Any("/delete", deleteuser)
router.Run()
}
执行后发现,在m1中添加了c.Abort()函数后,后续的m2和路由函数都不执行了。所以此函数就是当判断用户的请求不符合要求的时候,直接拒绝掉。不执行后续的函数。
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func m1(c *gin.Context) {
fmt.Println("我是m1之前")
fmt.Println("我是m1之后")
}
func m2(c *gin.Context) {
fmt.Println("我是m2")
}
func rootfunc(c *gin.Context) {
fmt.Println("我是/")
}
func main() {
router := gin.Default()
router.Use(m1, m2)
router.GET("/", rootfunc)
router.Run()
}
执行结果如下:
先把m1执行完,在执行m2执行完,在执行路由函数
我是m1之前
我是m1之后
我是m2
我是/
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func m1(c *gin.Context) {
fmt.Println("我是m1之前")
c.Next()
fmt.Println("我是m1之后")
}
func m2(c *gin.Context) {
fmt.Println("我是m2")
}
func rootfunc(c *gin.Context) {
fmt.Println("我是/")
}
func main() {
router := gin.Default()
router.Use(m1, m2)
router.GET("/", rootfunc)
router.Run()
}
执行结果如下:
我是m1之前
我是m2
我是/
我是m1之后