Go --- gin基础知识点(二)

简介: Go --- gin基础知识点

路由组

  • 用来管理有相同的URL的路由

使用示例:

package main
import (
    "fmt"
    "github.com/gin-gonic/gin"
)
// 路由组
func main() {
    // 1.创建路由
    // 默认使用了2个中间件Logger(), Recovery()
    r := gin.Default()
    // 路由组1 ,处理GET请求
    v1 := r.Group("/v1")
    // {} 是书写规范
    {
        v1.GET("/login", login)
        v1.GET("submit", submit)
    }
    v2 := r.Group("/v2")
    {
        v2.POST("/login", login)
        v2.POST("/submit", submit)
    }
    r.Run(":8000")
}
func login(c *gin.Context) {
    name := c.DefaultQuery("name", "jack")
    c.String(200, fmt.Sprintf("hello %s\n", name))
}
func submit(c *gin.Context) {
    name := c.DefaultQuery("name", "lily")
    c.String(200, fmt.Sprintf("hello %s\n", name))
}

访问失败页面

使用r.NoRoute来设置

例如:

r.NoRoute(func(c *gin.Context) {
        c.String(http.StatusNotFound, "sorry,天太冷了,页面跑去钻小被窝了")
})

结果:

gin路由原理

gin数据解析和绑定

Json数据解析和绑定

  • 客户端传参,Json格式,服务端解析到结构体
  • 使用gin.Context.ShouldBindJSON(&json) err将接收到的json数据解析到结构体中
User    string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`
Pssword string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
  • 解析中binding中的required该字段表示必须传参,如果不传参则会报错

表单数据解析和绑定

  • 使用gin.Context.Bind(&form) err 将接收到的表单数据解析到结构体中
··<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>表单提交数据解析到结构体</title>
</head>
<body>
    <form action="http://localhost:8000/loginForm" method="post" enctype="application/x-www-form-urlencoded">
    用户名:<input type="text" name="username"><br>
    密&nbsp码:<input type="password" name="password"><br>
    <input type="submit" value="提交">
    </form>
</body>
</html>
package main
import (
    "github.com/gin-gonic/gin"
    "net/http"
)
type Login struct {
    // binding:"required"修饰的字段,若接收为空值,则报错,是必须字段
    User    string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`
    Pssword string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
}
func main() {
    // 1.创建路由
    // 默认使用了2个中间件Logger(), Recovery()
    r := gin.Default()
    // JSON绑定
    r.POST("/loginForm", func(c *gin.Context) {
        // 声明接收的变量
        var form Login
        // Bind()默认解析并绑定form格式
        // 根据请求头中content-type自动推断
        if err := c.Bind(&form); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
        // 判断用户名密码是否正确
        if form.User != "root" || form.Pssword != "admin" {
            c.JSON(http.StatusBadRequest, gin.H{"status": http.StatusBadRequest})
            return
        }
        c.JSON(http.StatusOK, gin.H{"status": http.StatusOK,"body":form})
    })
    r.Run(":8000")
}

结果:

URI数据解析和绑定

  • 使用gin.Context.ShouldBindUri(&login) err 解析uri数据到结构体中

示例:

func main() {
    // 1.创建路由
    // 默认使用了2个中间件Logger(), Recovery()
    r := gin.Default()
    // JSON绑定
    r.GET("/:user/:password", func(c *gin.Context) {
        // 声明接收的变量
        var login Login
        // Bind()默认解析并绑定form格式
        // 根据请求头中content-type自动推断
        if err := c.ShouldBindUri(&login); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
        // 判断用户名密码是否正确
        if login.User != "root" || login.Pssword != "admin" {
            c.JSON(http.StatusBadRequest, gin.H{"status": "304"})
            return
        }
        c.JSON(http.StatusOK, gin.H{"status": "200"})
    })
    r.Run(":8000")
}

结果:

gin 渲染

各种数据格式的响应

  • json、结构体、XML、YAML类似于java的properties、ProtoBuf
func main() {
    // 1.创建路由
    // 默认使用了2个中间件Logger(), Recovery()
    r := gin.Default()
    // 1.json
    r.GET("/someJSON", func(c *gin.Context) {
        c.JSON(200, gin.H{"message": "someJSON", "status": http.StatusOK})
    })
    // 2. 结构体响应
    r.GET("/someStruct", func(c *gin.Context) {
        var msg struct {
            Name    string
            Message string
            Number  int
        }
        msg.Name = "root"
        msg.Message = "message"
        msg.Number = 123
        c.JSON(http.StatusOK, msg)
    })
    // 3.XML
    r.GET("/someXML", func(c *gin.Context) {
        c.XML(200, gin.H{"message": "abc"})
    })
    // 4.YAML响应
    r.GET("/someYAML", func(c *gin.Context) {
        c.YAML(200, gin.H{"name": "zhangsan"})
    })
    // 5.protobuf格式,谷歌开发的高效存储读取的工具
    // 数组?切片?如果自己构建一个传输格式,应该是什么格式?
    //r.GET("/someProtoBuf", func(c *gin.Context) {
    //    reps := []int64{int64(1), int64(2)}
    //    // 定义数据
    //    label := "label"
    //    // 传protobuf格式数据
    //    data := &protoexample.Test{
    //        Label: &label,
    //        Reps:  reps,
    //    }
    //    c.ProtoBuf(200, data)
    //})
    r.Run(":8000")
}

XML页面结果:

HTML模板渲染

  • gin支持加载HTML模板, 然后根据模板参数进行配置并返回相应的数据,本质上就是字符串替换
  • LoadHTMLGlob()方法可以加载模板文件

html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{.title}}</title>
</head>
<body>
    <h1>{{.test}}</h1>
</body>
</html>

go文件:

package main
import (
    "github.com/gin-gonic/gin"
    "net/http"
)
// html模板渲染
func main() {
    r := gin.Default()
    // 加载模板文件
    r.LoadHTMLGlob("static/*")
    // 如果项目结构不同,也可以是
    // r.LoadHTMLGlob("static/**/*")
    r.GET("/index", func(c *gin.Context) {
        c.HTML(http.StatusOK, "index.html", gin.H{"title": "我是测试", "test": "这是一个测试文件"})
    })
    r.Run(":8000")
}

结果:

重定向

  • 使用 gin.Context.Redirect 进行重定向
package main
import (
    "github.com/gin-gonic/gin"
    "net/http"
)
// 重定向
func main() {
    r := gin.Default()
    r.GET("/index", func(c *gin.Context) {
        c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com")
    })
    r.Run(":8000")
}

同步异步

  • 同步:先执行再响应
  • 异步:先响应再执行
  • go的协程机制(goroutine)可以方便地实现异步处理
  • 另外,在启动新的goroutine时,不应该使用原始上下文,必须使用它的只读副本
package main
import (
    "github.com/gin-gonic/gin"
    "log"
    "time"
)
// 同步异步
func main() {
    // 1.创建路由
    // 默认使用了2个中间件Logger(), Recovery()
    r := gin.Default()
    // 1.异步
    r.GET("/long_async", func(c *gin.Context) {
        // 需要搞一个副本
        copyContext := c.Copy()
        // 异步处理
        go func() {
            time.Sleep(30 * time.Second)
            log.Println("异步执行:" + copyContext.Request.URL.Path)
        }()
    })
    // 2.同步
    r.GET("/long_sync", func(c *gin.Context) {
        time.Sleep(30 * time.Second)
        log.Println("同步执行:" + c.Request.URL.Path)
    })
    r.Run(":8000")
}

结果:

相关文章
|
8天前
|
中间件 Go 数据库
Go开发者必读:Gin框架的实战技巧与最佳实践
在当今快速发展的互联网时代,Web开发的需求日益增长。Go语言以其简洁、高效、并发性强的特点,成为了开发者们的首选。而在Go语言的众多Web框架中,Gin无疑是其中的佼佼者。本文将深入探讨Gin框架的特性、优势以及如何利用Gin构建高性能的Web应用。
|
7天前
|
SQL 安全 前端开发
Go语言Gin框架安全加固:全面解析SQL注入、XSS与CSRF的解决方案
Go语言Gin框架安全加固:全面解析SQL注入、XSS与CSRF的解决方案
|
7天前
|
Java Go 调度
Go语言并发编程原理与实践:面试经验与必备知识点解析
【4月更文挑战第12天】本文分享了Go语言并发编程在面试中的重要性,包括必备知识点和面试经验。核心知识点涵盖Goroutines、Channels、Select、Mutex、Sync包、Context和错误处理。面试策略强调结构化回答、代码示例及实战经历。同时,解析了Goroutine与线程的区别、Channel实现生产者消费者模式、避免死锁的方法以及Context包的作用和应用场景。通过理论与实践的结合,助你成功应对Go并发编程面试。
28 3
|
7月前
|
开发框架 Go 微服务
Golang 语言怎么使用 go-micro 和 gin 开发微服务?
Golang 语言怎么使用 go-micro 和 gin 开发微服务?
144 0
|
8天前
|
关系型数据库 MySQL Go
go语言使用Gin框架链接数据库
go语言使用Gin框架链接数据库
45 0
|
8天前
|
JavaScript 前端开发 NoSQL
go embed 实现gin + vue静态资源嵌入
go embed 实现gin + vue静态资源嵌入
125 0
|
8天前
|
中间件 Go
go 打印gin 中的c.Request的参数
在 Gin 框架中,可以通过 `c.Request` 获取请求对象,从而访问请求的参数。以下是一个示例,展示如何打印出 `c.Request` 中的参数: ```go package main import ( "fmt" "github.com/gin-gonic/gin" ) func LoggerMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // 打印请求方法和路径 fmt.Printf("开始处理请求: %s %s\n", c.Request.Method, c.Request.URL.Pa
101 0
|
6月前
|
前端开发 Java 数据库连接
基于Gin+Gorm框架搭建MVC模式的Go语言企业级后端系统
基于Gin+Gorm框架搭建MVC模式的Go语言企业级后端系统
108 0
|
7月前
|
缓存 前端开发 中间件
Go 框架 Gin 怎么实现允许前端跨域请求?
Go 框架 Gin 怎么实现允许前端跨域请求?
59 0
|
7月前
|
JSON 中间件 Go
Go语言学习 - RPC篇:gin框架的基础能力剖析
gin是非常流行的一款HTTP框架。相较于原生的HTTP server,gin有很多改进点,主要在于3点: 1. 上手简单,开发思路与原生HTTP基本一致 2. 引入多个工具库,提高了开发效率 3. 生态丰富,有许多开源的组件 围绕着gin框架,我们将展开今天的话题。
117 2
Go语言学习 - RPC篇:gin框架的基础能力剖析