<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
官方地址:gin-gonic.com/docs/
下載並安裝Gin包,並匯入參照
$ go get -u github.com/gin-gonic/gin //將gin引入到程式碼中 import "github.com/gin-gonic/gin" //可選。如果使用諸如 http.StatusOK 之類的常數,則需要引入 net/http 包 import "net/http"
編寫如下測試程式碼
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() // 監聽並在 0.0.0.0:8080 上啟動服務 }
然後在瀏覽器中進行測試: http://localhost:8080 就可以存取到響應的請求。
下面展示幾種其他 常規 請求方式
// 下面列出常用幾種請求方式 r.GET("/someGet", handle) r.POST("/somePost", handle) r.PUT("/somePut", handle) r.DELETE("/someDelete", handle) r.PATCH("/somePatch", handle) r.HEAD("/someHead", handle) r.OPTIONS("/someOptions", handle) r.Any("/any", handle)
**還可以對請求進行分組操作。 **
v1 := r.Group("/v1") { v1.GET("/login", handle) } v2 := r.Group("/v2") { v2.GET("/login", handle) }
下面例子 是** 獲得請求中path**
func main() { router := gin.Default() // 匹配/user/john router.GET("/user/:name", func(c *gin.Context) { name := c.Param("name") c.String(http.StatusOK, "Hello %s", name) }) // 匹配/user/john/和/user/john/send 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") }
/user/:name/*action : 表示對後邊路由全部模糊匹配。例如:/user/john/send/1 形式 action會匹配得到 name 是 john, action是 /send/1
func main() { router := gin.Default() // welcome?firstname=Jane&lastname=Doe router.GET("/user", func(c *gin.Context) { firstname := c.DefaultQuery("name", "kim") // 獲取query中的name,沒有的話就為kim lastname := c.Query("age") // 獲取query中的age c.String(http.StatusOK, "Hello %s %s", firstname, lastname) }) router.Run(":8080") }
func main() { router := gin.Default() router.POST("/form_post", func(c *gin.Context) { message := c.PostForm("age") nick := c.DefaultPostForm("name", "kim") c.JSON(200, gin.H{ "status": "posted", "message": message, "nick": nick, }) }) router.Run(":8080") }
curl http://127.0.0.1:8080/form_post -X POST -d 'name=john&age=25'
通過此curl傳送post請求,即可獲得表單中資料。
基本用法
我們已經見識了x-www-form-urlencoded型別的引數處理,現在越來越多的應用習慣使用JSON來通訊,也就是無論返回的response還是提交的request,其content-type型別都是application/json的格式。而對於一些舊的web表單頁還是x-www-form-urlencoded的形式,這就需要我們的伺服器能支援住這多種content-type的引數了。
由於go是靜態語言,需要先實現定義資料模型,這就需要用到gin的model bind功能了。
gin使用go-playground/validator.v8驗證引數,檢視完整檔案。
需要在繫結的欄位上設定tag,比如,繫結格式為json,需要這樣設定json:"fieldname" 。
此外,Gin還提供了兩套繫結方法:
1.Must bind
c.AbortWithError(400, err).SetType(ErrorTypeBind),
響應狀態程式碼會被設定為400,請求頭Content-Type被設定為text/plain; charset=utf-8。
注意,如果你試圖在此之後設定響應程式碼,將會發出一個警告 [GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422,如果你希望更好地控制行為,請使用ShouldBind相關的方法
2.Should bind
當我們使用繫結方法時,Gin會根據Content-Type推斷出使用哪種繫結器,如果你確定你係結的是什麼,你可以使用MustBindWith或者BindingWith。
你還可以給欄位指定特定規則的修飾符,如果一個欄位用binding:"required"修飾,並且在繫結時該欄位的值為空,那麼將返回一個錯誤。
type Person struct { Name string `json:"name" binding:"required"` // json格式從name取值,並且該值為必須的 Age int `json:"age" binding:"required,gt=20"` // json格式從age取值,並且該值為必須的,且必須大於20 } func main() { router := gin.Default() router.POST("/test", func(context *gin.Context) { var person Person // 這裡我確定傳過來的一定是JSON所以用ShouldBindJSON,否則可以用ShouldBind if err := context.ShouldBindJSON(&person); err != nil { context.JSON(http.StatusBadRequest, gin.H{ "error": err.Error(), }) return } context.JSON(http.StatusOK, gin.H{ "success": true, }) }) router.Run(":8080") }
curl http://localhost:8080/test -X POST -d '{"name":"Rock","age": 25}'
上面是通過json對映方式 繫結 請求資料,並且對請求資料進行驗證。
驗證包 gopkg.in/go-playground/validator.v8使用方法
package main import ( "net/http" "reflect" "time" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" "gopkg.in/go-playground/validator.v8" ) type Booking struct { // 這裡的驗證方法為bookabledate CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"` // gtfield=CheckIn表示大於的欄位為CheckIn CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"` } func bookableDate( v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string, ) bool { // 這裡有兩個知識點,對映和斷言 // 在這裡,field是一個reflect.Type的介面型別變數,通過Interface方法獲得field介面型別變數的真實型別,可以理解為reflect.Value的逆操作 // 在這裡,斷言就是將一個介面型別的變數轉化為time.Time,前提是後者必須實現了前者的介面 // 綜上,這裡就是將field進行了型別轉換 if date, ok := field.Interface().(time.Time); ok { today := time.Now() if today.Year() > date.Year() || today.YearDay() > date.YearDay() { return false } } return true } func main() { route := gin.Default() // 註冊自定義驗證器 if v, ok := binding.Validator.Engine().(*validator.Validate); ok { v.RegisterValidation("bookabledate", bookableDate) } route.GET("/bookable", getBookable) route.Run(":8080") } func getBookable(c *gin.Context) { var b Booking if err := c.ShouldBindWith(&b, binding.Query); err == nil { c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"}) } else { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) } }
上面方法自定義了一種引數驗證器。
├── conf #專案組態檔目錄 │ └── config.toml #大家可以選擇自己熟悉的組態檔管理工具包例如:toml、xml等等 ├── controllers #控制器目錄,按模組存放控制器(或者叫控制器函數),必要的時候可以繼續劃分子目錄。 │ ├── food.go │ └── user.go ├── main.go #專案入口,這裡負責Gin框架的初始化,註冊路由資訊,關聯控制器函數等。 ├── models #模型目錄,負責專案的資料儲存部分,例如各個模組的Mysql表的讀寫模型。 │ ├── food.go │ └── user.go ├── static #靜態資源目錄,包括Js,css,jpg等等,可以通過Gin框架設定,直接讓使用者存取。 │ ├── css │ ├── images │ └── js ├── logs #紀錄檔檔案目錄,主要儲存專案執行過程中產生的紀錄檔。 └── views #檢視模板目錄,存放各個模組的檢視模板,當然有些專案只有api,是不需要檢視部分,可以忽略這個目錄 └── index.html
為方便偵錯,Gin 框架在執行的時候預設是debug模式,在控制檯預設會列印出很多偵錯紀錄檔,上線的時候我們需要關閉debug模式,改為release模式。
設定Gin框架執行模式:
通過環境變數設定 export GIN_MODE=release
GIN_MODE環境變數,可以設定為debug或者release
通過程式碼設定
在main函數,初始化gin框架的時候執行下面程式碼 // 設定 release模式 gin.SetMode(gin.ReleaseMode) // 或者 設定debug模式 gin.SetMode(gin.DebugMode)
route.GET("/ip", func(c *gin.Context) { // 獲取使用者IP ip := c.ClientIP() c.JSON(http.StatusBadRequest, gin.H{"ip": ip}) })
func (c *Context) String(code int, format string, values ...interface{}) c.String(200,"歡迎存取%s, 你是%s", "tizi360.com!","最靚的仔!")
我們開發api介面的時候常用的格式就是json,下面是返回json格式資料的例子
// User 定義 type User struct { Name string `json:"name"` // 通過json標籤定義struct欄位轉換成json欄位的名字。 Email string `json:"email"` } // Handler 控制器 func(c *gin.Context) { //初始化user物件 u := &User{ Name: "tizi365", Email: "tizi@tizi365.com", } //返回json資料 //返回結果:{"name":"tizi365", "email":"tizi@tizi365.com"} c.JSON(200, u) }
c.FileAttachment("/var/www/1.jpg", "1.jpg")
func(c *gin.Context) { //設定http響應 header, key/value方式,支援設定多個header c.Header("site","tizi365") }
func main() { // 初始化gin物件 router := gin.Default() // 首先載入templates目錄下面的所有模版檔案,模版副檔名隨意 router.LoadHTMLGlob("templates/*") // 繫結一個url路由 /index router.GET("/index", func(c *gin.Context) { // 通過HTML函數返回html程式碼 // 第二個引數是模版檔案名字 // 第三個引數是map型別,代表模版引數 // gin.H 是map[string]interface{}型別的別名 c.HTML(http.StatusOK, "index.html", gin.H{ "title": "Main website", }) }) // 啟動http服務,並且繫結在8080埠 router.Run(":8080") }
func main() { router := gin.Default() // 設定靜態資原始檔目錄,並且繫結一個Url字首 // 靜態資原始檔目錄:/var/www/tizi365/assets // /assets是存取靜態資源的url字首 // 例如: // /assets/images/1.jpg 這個url檔案,儲存在/var/www/tizi365/assets/images/1.jpg router.Static("/assets", "/var/www/tizi365/assets") // 為單個靜態資原始檔,繫結url // 這裡的意思就是將/favicon.ico這個url,繫結到./resources/favicon.ico這個檔案 router.StaticFile("/favicon.ico", "./resources/favicon.ico") // Listen and serve on 0.0.0.0:8080 router.Run(":8080") }
package main import ( "fmt" "github.com/gin-gonic/gin" ) func main() { router := gin.Default() // 設定cookie路由 router.GET("/setCookie", func(c *gin.Context) { // 設定cookie c.SetCookie("site_cookie", "cookievalue", 3600, "/", "localhost", false, true) }) // 獲得cookie路由 router.GET("/cookie", func(c *gin.Context) { data, err := c.Cookie("/cookie") fmt.Printf(data) if err != nil { // 直接返回cookie值 c.String(200, data) return } c.String(200, "not found!") }) //刪除cookie路由 router.GET("/removeCookie", func(c *gin.Context) { c.SetCookie("set_cookie", "cookievalue", -1, "/", "localhost", false, true) c.String(200, "刪除cookie") }) router.Run(":8080") }
package main // 匯入gin包 import ( "fmt" "github.com/gin-gonic/gin" "log" "net/http" ) func main() { router := gin.Default() // 設定檔案上傳大小限制,預設是32m router.MaxMultipartMemory = 64 << 20 // 64 MiB router.POST("/upload", func(c *gin.Context) { // 獲取上傳檔案,返回的是multipart.FileHeader物件,代表一個檔案,裡面包含了檔名之類的詳細資訊 // file是表單欄位名字 file, _ := c.FormFile("file") // 列印上傳的檔名 log.Println(file.Filename) // 將上傳的檔案,儲存到./data/1111.jpg 檔案中 c.SaveUploadedFile(file, "./data/1111.jpg") c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename)) }) router.Run(":8080") }
在Gin框架中,中介軟體(Middleware)指的是可以攔截http請求-響應生命週期的特殊函數,在請求-響應生命週期中可以註冊多箇中介軟體,每個中介軟體執行不同的功能,一箇中間執行完再輪到下一個中介軟體執行。
中介軟體的常見應用場景如下:
Gin支援設定全域性中介軟體和針對路由分組設定中介軟體,設定全域性中介軟體意思就是會攔截所有請求,針對分組路由設定中介軟體,意思就是僅對這個分組下的路由起作用。
package main // 匯入gin包 import ( "fmt" "github.com/gin-gonic/gin" "log" "time" ) // 自定義個紀錄檔中介軟體 func Logger() gin.HandlerFunc { return func(c *gin.Context) { t := time.Now() // 可以通過上下文物件,設定一些依附在上下文物件裡面的鍵/值資料 c.Set("example", "12345") fmt.Printf("1. 執行中介軟體設定 n") // 在這裡處理請求到達控制器函數之前的邏輯 // 呼叫下一個中介軟體,或者控制器處理常式,具體得看註冊了多少箇中介軟體。 c.Next() fmt.Printf("4. 完成 執行中介軟體設定 n") // 在這裡可以處理請求返回給使用者之前的邏輯 latency := time.Since(t) log.Print(latency) // 例如,查詢請求狀態嗎 status := c.Writer.Status() log.Println(status) } } func main() { r := gin.New() // 註冊上面自定義的紀錄檔中介軟體 r.Use(Logger()) r.GET("/test", func(c *gin.Context) { // 查詢我們之前在紀錄檔中介軟體,注入的鍵值資料 fmt.Printf("2. 開始執行業務邏輯 n") example := c.MustGet("example").(string) // it would print: "12345" log.Println(example) fmt.Printf("3. 業務邏輯執行完成 n") }) // Listen and serve on 0.0.0.0:8080 r.Run(":8080") }
其輸出結果如下:
1. 執行中介軟體設定
2. 開始執行業務邏輯
2022/10/22 16:33:29 12345
3. 業務邏輯執行完成
4. 完成 執行中介軟體設定
2022/10/22 16:33:29 658.681µs
2022/10/22 16:33:29 200
Gin 中介軟體類似 Node中的洋蔥模型。
以上就是Golang中Gin框架的使用入門教學的詳細內容,更多關於Golang Gin框架的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45