Gin框架的学习(上) | 青训营

243 阅读7分钟

今天是第六届青训营笔记打卡的第四天 本文主要内容是Gin框架学习的部分内容,主要包括以下三个方面 :

  1. 安装go和gin框架
  2. Gin的初体验
  3. Gin框架对各种XX的响应

安装go和gin

安装go

下载网址 :

studygolang.com/dl

go.dev/dl/

直接将解压的bin添加到环境目录即可

验证go环境

go version

编写一个hello.go的文件,文件内容为

package main
import "fmt"
func main() {
   fmt.Println("Hello, World!")
}

通过编译器运行go文件

go run hello.go

如果出现“Hello World!”就说明运行成功了,当然,我们肯定需要一个趁手的IDE工具才行

goland编辑器下载

www.jetbrains.com/go/download…

和pycharm的安装方式类似

配置代理

在使用go的时候,会需要安装一些第三方包

如果不配置代理,那么则会从go的官网上去拉取第三方包

img

GOPROXY=https://goproxy.cn,direct

安装gin

在终端输入 :

 go get github.com/gin-gonic/gin

就会自动获取gin;

Gin的初体验

Hello World

编程学习到新东西第一件事 就是 "Hello World"

代码 :

package main
​
import (
    "github.com/gin-gonic/gin"
    "net/http"
)
​
func Index(context *gin.Context) {
    context.String(200, "Hello World")
}
​
func main() {
    // 创建一个默认的路由
    router := gin.Default()
​
    // 绑定路由规则和路由函数,访问/index的路由,将由对应的函数去处理
    router.GET("/index", Index)
​
    // 启动监听,gin会把web服务器运行在本机的8080端口上
    // 启动方式一 :
    router.Run(":8080")
    // 启动方式二 : 原生http服务的方式
    http.ListenAndServe(":8080", router)
​
}
​

代码详解 :

  1. router:=gin.Default():这是默认的服务器。使用gin的Default方法创建一个路由Handler
  2. 然后通过Http方法绑定路由规则和路由函数。不同于net/http库的路由函数,gin进行了封装,把requestresponse都封装到了gin.Context的上下文环境中。
  3. 最后启动路由的Run方法监听端口。还可以用http.ListenAndServe(":8080", router),或者自定义Http服务器配置。

注意 : 在8080前面一定要加上 : 。

GO中GET方法的具体实现 :

// GET is a shortcut for router.Handle("GET", path, handlers).
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
    return group.handle(http.MethodGet, relativePath, handlers)
}

Go中ListenAndServer的具体实现 :

func ListenAndServe(addr string, handler Handler) error {
    server := &Server{Addr: addr, Handler: handler}
    return server.ListenAndServe()
}

gin的两种启动方式 :

    // 启动方式一 : 
    router.Run(":8080")
    // 启动方式二 : 
    http.ListenAndServe(":8080",router)

运行

打开浏览器,在地址栏输入 :

127.0.0.1:8080

出现以下界面,就代表gin开始工作了。

image-20230809223756955.png

将地址栏输入改为

127.0.0.1:8080/index

出现以下界面 :

image-20230809223935738.png

成功运行程序,输出Hello World!!!

关于gin中的context,gin.Context

在 Gin 中,Context 是一个非常重要的概念,用于处理 HTTP 请求和响应。在 Gin 的处理流程中,Context 贯穿整个处理过程,用于传递请求和响应的信息。

在 Gin 中,Context 是一个非常重要的概念,用于处理 HTTP 请求和响应。在 Gin 的处理流程中,Context 贯穿整个处理过程,用于传递请求和响应的信息。

Gin 的 Context 是一个结构体类型,定义如下:

type Context struct {
    // 定义了一些私有成员变量,用于存储请求和响应等信息
    // ...
}

Context 中封装了原生的 Go HTTP 请求和响应对象,同时还提供了一些方法,用于获取请求和响应的信息、设置响应头、设置响应状态码等操作。

在 Gin 中,Context 是通过中间件来传递的。在处理 HTTP 请求时,Gin 会依次执行注册的中间件,每个中间件可以对 Context 进行一些操作,然后将 Context 传递给下一个中间件。

例如,下面是一个简单的中间件,用于在请求头中设置一个自定义的 X-Request-ID:

func RequestIDMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        requestID := generateRequestID()
        c.Request.Header.Set("X-Request-ID", requestID)
        c.Next()  // 将 Context 传递给下一个中间件
    }
}

在上面的中间件中,我们生成了一个请求 ID,然后将其设置到请求头中。接着,调用 c.Next() 方法将 Context 传递给下一个中间件。这样,下一个中间件就可以通过 c.Request.Header.Get("X-Request-ID") 获取到这个请求 ID。

总之,在 Gin 中,Context 是通过中间件来传递的。每个中间件都可以对 Context 进行一些操作,然后将其传递给下一个中间件,最终由处理函数来使用 Context 中的信息进行处理。

响应

200 表示正常响应 http.StatusOK

响应字符串

router.GET("/txt", func(c *gin.Context) {
  c.String(http.StatusOK, "返回txt")
})

响应json

package main
​
import (
    "github.com/gin-gonic/gin"
    "net/http"
)
func _json(c *gin.Context) {
    c.JSON(200, 2)
}
func main() {
    router := gin.Default()
    router.GET("/json", _json)
    router.Run(":80")
}

运行效果 :

image-20230810202856034.png

响应结构体,map,和直接响应json :

func _json(c *gin.Context) {
    json响应结构体
    type Userinfo struct {
        UserName string `json:"user_name"`
        Age      int    `json:"age"`
        PassWord string `json:"-"` // 打 '-' 表示忽略转化为json
    }
    user := Userinfo{"大黄", 8, "123456"}
    c.JSON(200, Userinfo)
​
    // json响应map
    //userMap := map[string]string{
    //  "user_name": "大黄",
    //  "age":       "8",
    //}
    //c.JSON(200, userMap)//直接响应json
    //c.JSON(200, gin.H{"user_anme": "大黄", "age": 8})
}

运行效果 :

image-20230810204346506.png

响应xml

func _xml(c *gin.Context) {
    c.XML(200, gin.H{"user": "ys", "message": "hello", "status": http.StatusOK, "data": gin.H{"username": "大黄", "age": 8}})
}

运行效果 :

image-20230810210101999.png

响应yaml

func _yaml(c *gin.Context) {
    c.YAML(200, gin.H{"user": "ys", "message": "hello", "status": http.StatusOK, "data": gin.H{"username": "大黄", "age": 8}})
}

运行效果: 由于浏览器原因,使用postman工具;

image-20230810211038386.png

返回html

先创建一个模板目录 :templates

image-20230810212428931.png

使用 LoadHTMLGlob()或者LoadHTMLFiles()方法来加载模板文件,一般放在router声明后 :

// 加载模板目录下所有的模板文件router.LoadHTMLGlob("templates/*") // 表示加载templates下所有的文件

index.html文件 :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<header>
    你好啊! {{.username}}
</header>
</body>
</html>

例 :

func _html(c *gin.Context) {
    c.HTML(200, "index.html", gin.H{"username": "大黄"})
}

运行效果 :

image-20230810212746327.png

注意 :

  • 在模板中使用这个title,需要使用{{ .title }}
  • 不同文件夹下模板名字可以相同,此时需要 LoadHTMLGlob() 加载两层模板路径。
router.LoadHTMLGlob("templates/**/*")
router.GET("/posts/index", func(c *gin.Context) {
    c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
        "title": "Posts",
    })
    c.HTML(http.StatusOK, "users/index.tmpl", gin.H{
        "title": "Users",
    })
​
})

文件响应

结构 :

image-20230810224907009.png

// 在go中,没有相对文件的路径,只有相对于项目的路径
    // 网页请求这个静态目录的前缀,第二个参数是一个目录,注意:前缀不能重复
    router.StaticFS("/static", http.Dir("static/static"))
    // 配置单个文件   网络请求的路由,文件的路径
    router.StaticFile("/title.png", "static/hler.png")

整体代码 :

package main
​
import (
    "github.com/gin-gonic/gin"
    "net/http"
)
​
func main() {
    router := gin.Default()
    // 在go中,没有相对文件的路径,只有相对于项目的路径
    // 网页请求这个静态目录的前缀,第二个参数是一个目录,注意:前缀不能重复
    router.StaticFS("/static", http.Dir("static/static"))
    // 配置单个文件   网络请求的路由,文件的路径
    router.StaticFile("/hler.png", "static/hler.png")
    router.Run(":80")
}

运行效果 :

在地址栏输入 : http://127.0.0.1/hler.png

对应 :

    router.StaticFile("/hler.png", "static/hler.png")

image-20230810224438243.png

在地址栏输入 : http://127.0.0.1/static/qqh

对应 :

    router.StaticFS("/static", http.Dir("static/static"))

image-20230810224520313.png

而输入 : http://127.0.0.1/static/pwd

image-20230810224711896.png

因为没有对pwd,txt文件进行配置,所以访问不到,这样就可以将自己不想公开的文件不能进行访问。

重定向

重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置

router.GET("/redirect", func(c *gin.Context) {
    //支持内部和外部的重定向
    c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com/")
})

对于重定向,我们就实现到百度的跳转吧!!!

代码 :

package main
​
import (
    "github.com/gin-gonic/gin"
    "net/http"
)
// 重定向
func _redirect(c *gin.Context) {
    c.Redirect(302, "https://www.baidu.com/")
}
​
func main() {
    router := gin.Default()
    router.SetTrustedProxies([]string{"127.0.0.1"})
    router.GET("/baidu", _redirect)
    router.Run(":80")
}

对于

router.SetTrustedProxies([]string{"127.0.0.1"})

这一行 : 如果遇到goland里面报错 :

[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.

那么就加上这一行,来给gin设置一个信任的ip

运行 :

在地址栏里面输入 : 127.0.0.1/baidu

就能直接跳转到百度界面了!!!

image-20230810233325236.png

两种状态码:

  • 301 Moved Permanently

被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的。

  • 302 Found

请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。

如有问题,大佬们看见还请提出,我必改正, 另外,欢迎留言交流!