Gin篇:Gin基础

 

安装Gin

1、配置代理

请查看:https://github.com/goproxy/goproxy.cn/blob/master/README.zh-CN.md

1
2
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

2、go get -u -v github.com/gin-gonic/gin

1
2
-v:打印出被构建的代码包的名字
-u:已存在相关的代码包,强行更新代码包及其依赖包

3.部分包无法安装

1
crypto无法下载解决方式:
1
2
3
1.进入$GOPATH(你的安装go 的路径)
2.进入 $GOPATH/src, 创建文件夹 golang.org, 以及子文件夹 golang.org/x
3.进$GOPATH/golang.org/x 使用如下命令:4.git clone https://github.com/golang/crypto.git
1
protobuf无法下载解决方式:
1
2
3
4
1.进入$GOPATH(你的安装go 的路径)
2.进入 $GOPATH/src, 创建文件夹 google.golang.org,以及子文件google.golang.org/protobuf
3.将 google.golang.org/protobuf 包对应的github上的代码下载下来,github地址:https://github.com/protocolbuffers/protobuf-go 
4.将下载下来的protobuf-go/目录下的全部文件复制到 "google.golang.org/protobuf "

  

第一个Gin程序

1
2
3
4
5
6
7
8
9
10
11
12
13
package main
 
import "github.com/gin-gonic/gin"
 
func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run(":8200") // listen and serve on 0.0.0.0:8200
}
  1. 首先,我们使用了gin.Default()生成了一个实例,这个实例即 WSGI 应用程序。
  2. 接下来,我们使用r.Get("/", ...)声明了一个路由,告诉 Gin 什么样的URL 能触发传入的函数,这个函数返回我们想要显示在用户浏览器中的信息。
  3. 最后用 r.Run()函数来让应用运行在本地服务器上,默认监听端口是 8200,可以传入参数设置端口,例如r.Run(":9999")即运行在 9999端口。
1
2
3
4
5
6
7
8
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
 
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)
 
[GIN-debug] GET    /ping                     --> main.main.func1 (3 handlers)
[GIN-debug] Listening and serving HTTP on :8000

 

 

 

 

 

路由(Route)

路由方法有 GET, POST, PUT, PATCH, DELETE 和 OPTIONS,还有Any,可匹配以上任意类型的请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func main() {
    // Disable Console Color
    // gin.DisableConsoleColor()
 
    // 使用默认中间件创建一个gin路由器
    // logger and recovery (crash-free) 中间件
    router := gin.Default()
 
    router.GET("/someGet", getting)
    router.POST("/somePost", posting)
    router.PUT("/somePut", putting)
    router.DELETE("/someDelete", deleting)
    router.PATCH("/somePatch", patching)
    router.HEAD("/someHead", head)
    router.OPTIONS("/someOptions", options)
 
    // 默认启动的是 8080端口,也可以自己定义启动端口
    router.Run()
    // router.Run(":3000") for a hard coded port
}

解析路径参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func main() {
    router := gin.Default()
 
    // 此规则能够匹配/user/john这种格式,但不能匹配/user/ 或 /user这种格式
    router.GET("/user/:name", func(c *gin.Context) {
        name := c.Param("name")
        c.String(http.StatusOK, "Hello %s", name)
    })
 
    // 但是,这个规则既能匹配/user/john/格式也能匹配/user/john/send这种格式
    // 如果没有其他路由器匹配/user/john,它将重定向到/user/john/
    router.GET("/user/:name/*action", func(c *gin.Context) {
        name := c.Param("name")
        action := c.Param("action")
        message := name + " is " + action
        c.String(http.StatusOK, message)
    })
 
    router.Run(":8080")
}

获取Get参数

1
2
3
4
5
6
7
8
9
10
11
12
func main() {
    router := gin.Default()
 
    // 匹配的url格式:  /welcome?firstname=Jane&lastname=Doe
    router.GET("/welcome", func(c *gin.Context) {
        firstname := c.DefaultQuery("firstname", "Guest")
        lastname := c.Query("lastname") // 是 c.Request.URL.Query().Get("lastname") 的简写
 
        c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
    })
    router.Run(":8080")
}

获取Post参数

复制代码
func main() {
    router := gin.Default()

    router.POST("/form_post", func(c *gin.Context) {
        message := c.PostForm("message")
        nick := c.DefaultPostForm("nick", "anonymous") // 此方法可以设置默认值

        c.JSON(200, gin.H{
            "status":  "posted",
            "message": message,
            "nick":    nick,
        })
    })
    router.Run(":8080")
}
复制代码

Get + Post 混合

示例:
POST /post?id=1234&page=1 HTTP/1.1
Content-Type: application/x-www-form-urlencoded

name=manu&message=this_is_great
复制代码
func main() {
    router := gin.Default()

    router.POST("/post", func(c *gin.Context) {

        id := c.Query("id")
        page := c.DefaultQuery("page", "0")
        name := c.PostForm("name")
        message := c.PostForm("message")

        fmt.Printf("id: %s; page: %s; name: %s; message: %s", id, page, name, message)
    })
    router.Run(":8080")
}
复制代码
1
结果:id: 1234; page: 1; name: manu; message: this_is_great

路由分组

复制代码
func main() {
    router := gin.Default()

    // Simple group: v1
    v1 := router.Group("/v1")
    {
        v1.POST("/login", loginEndpoint)
        v1.POST("/submit", submitEndpoint)
        v1.POST("/read", readEndpoint)
    }

    // Simple group: v2
    v2 := router.Group("/v2")
    {
        v2.POST("/login", loginEndpoint)
        v2.POST("/submit", submitEndpoint)
        v2.POST("/read", readEndpoint)
    }

    router.Run(":8080")
}
复制代码

 

上传文件

单个文件

1
2
3
4
5
r.POST("/upload1", func(c *gin.Context) {
    file, _ := c.FormFile("file")
    // c.SaveUploadedFile(file, dst)
    c.String(http.StatusOK, "%s uploaded!", file.Filename)
})

多个文件

1
2
3
4
5
6
7
8
9
10
11
r.POST("/upload2", func(c *gin.Context) {
    // Multipart form
    form, _ := c.MultipartForm()
    files := form.File["upload[]"]
 
    for _, file := range files {
        log.Println(file.Filename)
        // c.SaveUploadedFile(file, dst)
    }
    c.String(http.StatusOK, "%d files uploaded!", len(files))
})

  

中间件(Middleware)

1
2
3
4
5
6
7
8
9
10
11
12
13
// 作用于全局
r.Use(gin.Logger())
r.Use(gin.Recovery())
 
// 作用于单个路由
r.GET("/benchmark", MyBenchLogger(), benchEndpoint)
 
// 作用于某个组
authorized := r.Group("/")
authorized.Use(AuthRequired())
{
    authorized.POST("/login", loginEndpoint)
    authorized.POST("/submit", submitEndpoint)
1
2
无中间件启动使用
r := gin.New()
1
2
// 默认启动方式,包含 Logger、Recovery 中间件
r := gin.Default()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
func main() {
    // 创建一个不包含中间件的路由器
    r := gin.New()
 
    // 全局中间件
    // 使用 Logger 中间件
    r.Use(gin.Logger())
 
    // 使用 Recovery 中间件
    r.Use(gin.Recovery())
 
    // 路由添加中间件,可以添加任意多个
    r.GET("/benchmark", MyBenchLogger(), benchEndpoint)
 
    // 路由组中添加中间件
    // authorized := r.Group("/", AuthRequired())
    // exactly the same as:
    authorized := r.Group("/")
    // per group middleware! in this case we use the custom created
    // AuthRequired() middleware just in the "authorized" group.
    authorized.Use(AuthRequired())
    {
        authorized.POST("/login", loginEndpoint)
        authorized.POST("/submit", submitEndpoint)
        authorized.POST("/read", readEndpoint)
 
        // nested group
        testing := authorized.Group("testing")
        testing.GET("/analytics", analyticsEndpoint)
    }
 
    // Listen and serve on 0.0.0.0:8080
    r.Run(":8080")
}

写日志文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func main() {
    // 禁用控制台颜色
    gin.DisableConsoleColor()
 
    // 创建记录日志的文件
    f, _ := os.Create("gin.log")
    gin.DefaultWriter = io.MultiWriter(f)
 
    // 如果需要将日志同时写入文件和控制台,请使用以下代码
    // gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
 
    router := gin.Default()
    router.GET("/ping", func(c *gin.Context) {
        c.String(200, "pong")
    })
 
    router.Run(":8080")
} 

自定义日志格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
func main() {
    router := gin.New()
 
    // LoggerWithFormatter 中间件会将日志写入 gin.DefaultWriter
    // By default gin.DefaultWriter = os.Stdout
    router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
 
        // 你的自定义格式
        return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
                param.ClientIP,
                param.TimeStamp.Format(time.RFC1123),
                param.Method,
                param.Path,
                param.Request.Proto,
                param.StatusCode,
                param.Latency,
                param.Request.UserAgent(),
                param.ErrorMessage,
        )
    }))
    router.Use(gin.Recovery())
 
    router.GET("/ping", func(c *gin.Context) {
        c.String(200, "pong")
    })
 
    router.Run(":8080")
}

输出:

1
::1 - [Fri, 07 Dec 2018 17:04:38 JST] "GET /ping HTTP/1.1 200 122.767µs "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36" "

  

 

posted @   -零  阅读(4935)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示