安裝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" "