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 } |
- 首先,我们使用了
gin.Default()
生成了一个实例,这个实例即 WSGI 应用程序。 - 接下来,我们使用
r.Get("/", ...)
声明了一个路由,告诉 Gin 什么样的URL 能触发传入的函数,这个函数返回我们想要显示在用户浏览器中的信息。 - 最后用
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 " " |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?