安装Gin
1、配置代理
请查看:https://github.com/goproxy/goproxy.cn/blob/master/README.zh-CN.md
go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.cn,direct
2、go get -u -v github.com/gin-gonic/gin
-v:打印出被构建的代码包的名字 -u:已存在相关的代码包,强行更新代码包及其依赖包
3.部分包无法安装
crypto无法下载解决方式:
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
protobuf无法下载解决方式:
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程序
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端口。
[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,可匹配以上任意类型的请求。
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 }
解析路径参数
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参数
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") }
结果: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") }
上传文件
单个文件
r.POST("/upload1", func(c *gin.Context) { file, _ := c.FormFile("file") // c.SaveUploadedFile(file, dst) c.String(http.StatusOK, "%s uploaded!", file.Filename) })
多个文件
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)
// 作用于全局 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)
无中间件启动使用 r := gin.New()
// 默认启动方式,包含 Logger、Recovery 中间件 r := gin.Default()
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") }
写日志文件
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") }
自定义日志格式
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 - [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" "