gin
快速体验
go
复制代码
func HandlerPong(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
}
func main() {
r := gin.Default()
r.GET("/ping", HandlerPong)
_ = r.Run(":8080")
}
restful 风格
- restful 与技术无关,代表的是一种软件架构风格,REST 是 Representational State Transfer 的简称,中文翻译为"表征状态转移"或"表现层状态转化"。
- RESTFUL 特点包括:
- 每一个 URI 代表 1 种资源;
- 客户端使用 GET、POST、PUT、DELETE4 个表示操作方式的动词对服务端资源进行操作:GET 用来获取资源,POST 用来新建资源(也可以用于更新资源),PUT 用来更新资源,DELETE 用来删除资源
- 通过操作资源的表现形式来操作资源;
- 资源的表现形式是 XML 或者 HTML;
- 客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息。
go
复制代码
func HandlerGet(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "get",
})
}
func HandlerPost(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "post",
})
}
func HandlerPut(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "put",
})
}
func HandlerDelete(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "delete",
})
}
func main() {
r := gin.Default()
r.GET("/get", HandlerGet)
r.POST("/post", HandlerPost)
r.PUT("/put", HandlerPut)
r.DELETE("/delete", HandlerDelete)
_ = r.Run(":8080")
}
路由分组
- 在我们实际的开发应用中我们希望能个各个功能模块的路由进行分组,同一个模块的不同路由带有同样的前缀
- 作用:首先是路由更加的清晰 并且我们在针对某一组路由进行中间件权限校验的时候也比较的方便。
go
复制代码
func handleLogin(c *gin.Context) {
}
func handleSubmit(c *gin.Context) {
}
func main() {
r := gin.Default()
v1 := r.Group("/api/v1")
{
v1.POST("/login", handleLogin)
v1.POST("/submit", handleSubmit)
}
v2 := r.Group("/api/v2")
{
v2.POST("/login", handleLogin)
v2.POST("/submit", handleSubmit)
}
}
动态参数获取
- 在 Gin 框架中,可以使用 c.Param("paramKey")来获取动态参数。这里的 paramKey 是你在路由定义中定义的参数名称。
go
复制代码
func handleGetInfo(c *gin.Context) {
id := c.Param("id")
action := c.Param("action")
c.JSON(http.StatusOK, gin.H{
"id": id,
"action": action,
})
}
func main() {
r := gin.Default()
r.GET("/info/:id/:action", handleGetInfo)
_ = r.Run(":8080")
}
get 参数获取
- 获取 GET 参数可以使用 c.Query 函数。这个函数接受一个参数名作为字符串,并返回匹配该参数名的第一个值。如果参数不存在,则返回空字符串。
go
复制代码
func handlerGetParams(c *gin.Context) {
name := c.DefaultQuery("name", "tom")
age := c.DefaultQuery("age", "18")
c.JSON(http.StatusOK, gin.H{
"name": name,
"age": age,
})
}
func main() {
r := gin.Default()
r.GET("/get-params", handlerGetParams)
_ = r.Run(":8080")
}
绑定结构体数据
- 我们可以使用 ShouldBind 系列方法来绑定请求中的数据到 Go 的结构体。这些方法支持 JSON,XML,form 等数据格式。
go
复制代码
type Person struct {
Id int `uri:"id" binding:"required" json:"id"`
Name string `uri:"name" binding:"required" json:"name"`
}
func handleParams(c *gin.Context) {
var person Person
if err := c.ShouldBindUri(&person); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, person)
}
func main() {
r := gin.Default()
r.GET("/ping", handleParams)
_ = r.Run(":8080")
}
post 参数获取 form-data 数据
- 获取 POST 参数可以通过 Context.PostForm()方法来实现。这个方法可以获取到 application/x-www-form-urlencoded 类型的数据。
go
复制代码
func handlePostParams(c *gin.Context) {
name := c.PostForm("name")
age := c.PostForm("age")
c.JSON(http.StatusOK, gin.H{
"name": name,
"age": age,
})
}
func main() {
r := gin.Default()
r.POST("/post-params", handlePostParams)
_ = r.Run(":8080")
}
post 参数获取 json
- 要获取 POST JSON 数据,你可以使用 Context.BindJSON()方法。
go
复制代码
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
func handlePostJson(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, user)
}
func main() {
r := gin.Default()
r.POST("/post-json", handlePostJson)
_ = r.Run(":8080")
}
返回 protobuf 数据
- 你需要做的是先将 Protobuf 数据序列化成二进制格式,然后设置正确的响应头,最后将二进制数据写入到 Response 中
go
复制代码
//protobuf
syntax = "proto3";
option go_package = ".;proto";
message Teacher{
string name = 1;
repeated string course = 2;
}
//---------------------------------------
func handleProtobuf(c *gin.Context) {
teacher := proto.Teacher{
Name: "tom",
Course: []string{"python", "java", "go"},
}
c.ProtoBuf(http.StatusOK, &teacher)
}
func main() {
r := gin.Default()
r.GET("/protobuf", handleProtobuf)
_ = r.Run(":8080")
}
from 表单验证 from-data
- 若要将请求体绑定到结构体中,需要使用模型绑定,支持 JSON、XML、YAML 和标准表单的绑定,设置时需要在绑定的字段上设置 tag,其只要有两套绑定方法
- Must bind
- 方法: Bind 、BindJSON、BindXML、BindQuery、BindYAML
- 行为:这些方法底层使用 MustBindWith 方法,如果存在绑定错误,请求将被终止,响应代码会被设置成 400
- 方法: ShouldBind、ShouldBindJSON、ShouldBindXML、ShouldBindQuery、ShouldBindYAML
- 行为:底层使用 ShouldBindWith 方法,如果存在绑定错误,则返回 go 语言的错误形式,开发人员可以处理错误,请求不会被终
go
复制代码
type LoginForm struct {
Name string `form:"name" binding:"required,min=2,max=10"`
Password string `form:"password" binding:"required,min=8,max=20"`
}
func handleLogin(c *gin.Context) {
var loginForm LoginForm
if err := c.ShouldBind(&loginForm); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, &loginForm)
}
func main() {
r := gin.Default()
r.POST("/login", handleLogin)
_ = r.Run(":8080")
}
from 表单验证 json
go
复制代码
type User struct {
Name string `json:"name" binding:"required,min=2,max=20"`
Password string `json:"password" binding:"required,min=8,max=20"`
}
func handleLogin(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, &user)
}
func main() {
r := gin.Default()
r.POST("/login", handleLogin)
_ = r.Run(":8080")
}
中间件 middleware
- 中间件(middleware)是一种独立的组件或模块,通常是一个函数或一组函数,常被用于处理请求或事件的过程中
- 中间件常用来实现一些通用的功能,如日志记录、权限校验、数据加工等
- 中间件流程控制函数包括:
- c.Next(): 调用该函数会将控制权交给下一个中间件函数,如果没有下一个中间件函数,则将控制权交给处理请求的路由处理函数
- c.Abort(): 调用该函数会立即终止当前中间件函数的执行,并且不会再调用后续的中间件函数或路由处理函数
- c.AbortWithStatus(code int): 调用该函数会终止当前中间件函数的执行,并返回指定的 HTTP 状态码给客户端
- c.NextWithError(): 调用该函数会将控制权交给下一个中间件函数,同时传递一个错误给下一个中间件函数或路由处理函数
- c.IsAborted(): 该函数用于判断当前请求是否已经被终止,返回一个布尔值表示请求是否已经被终止
go
复制代码
func handleUserInfo(c *gin.Context) {
c.JSON(200, gin.H{
"code": 200,
"name": "tom",
})
}
func main() {
r := gin.Default()
v1 := r.Group("/api/v1").Use(middleware.Logger())
{
v1.GET("/info", handleUserInfo)
}
_ = r.Run(":8080")
}
//------------------------------------------------
// middleware
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now()
c.Set("name", "tom")
c.Next()
end := time.Since(t)
fmt.Println(end)
}
}
优雅退出
- 在 Web 开发中,一个应用程序可能因为多种原因需要关闭,比如接收到关闭信号、处理完所有的请求或者遇到不可恢复的错误。优雅的退出机制可以确保应用程序在关闭过程中,能够完成正在处理的任务,释放资源,并向客户端提供适当的响应,从而保证服务的高可用性和数据的完整性。
go
复制代码
func handleExit(c *gin.Context) {
c.JSON(200, gin.H{
"code": 200,
"name": "tom",
})
}
func main() {
r := gin.Default()
r.GET("/", handleExit)
go func() {
_ = r.Run(":8080")
}()
// 接收信号
quit := make(chan os.Signal)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
fmt.Println("服务关闭中....")
}
贵州晓智信息科技有限公司