Gin Web Framework
brief introduction
- web framework developed based on httprouter: https://github.com/gin-gonic/gin
- Provides Martini style API, but 40 times faster than Martini
- Very lightweight, simple to use
Installation and use of Gin framework
- Install: go get -u github.com/gin-gonic/gin
Basic use
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:9090") }
restful API support
- Abstract the designed API into resources and identify them with URI s
- For each resource, use a unified method to operate
- Unified methods: GET,POST, PUT, DELETE
import ( "github.com/gin-gonic/gin" "net/http" ) type Result struct { Message string `json:"message"` Code int `json:"code"` } func handleUserInfo(c *gin.Context) { var result Result = Result{ Message: "hello", Code: 0, } c.JSON(http.StatusOK,result) } func main() { r := gin.Default() r.GET("/user/info", handleUserInfo) r.Run("0.0.0.0:9090") }
queryString design
- Query class: http://127.0.0.1:9090/user/info?username=dadasd&&passwd=1234
- Routing class: http://127.0.0.1:9090/user/info/2020/12
import ( "github.com/gin-gonic/gin" "net/http" ) type Result struct { Message string `json:"message"` Code int `json:"code"` } type UserInfo struct { Result UserName string `json:"username"` Passwd string `json:"passwd"` } func handleUserParams(c *gin.Context) { //Query class interface username := c.Query("username") passwd := c.DefaultQuery("passwd","adcdefg") var result UserInfo = UserInfo{ Result{ Message: "success", Code: 200, }, username, passwd, } c.JSON(http.StatusOK,result) } func handleUserInfo(c *gin.Context) { //Routing interface username := c.Param("username") passwd := c.Param("passwd") var result UserInfo = UserInfo{ Result{ Message: "success", Code: 200, }, username, passwd, } c.JSON(http.StatusOK,result) } func main() { r := gin.Default() r.GET("/user/info", handleUserParams) r.GET("/user/info/:username/:passwd", handleUserInfo) r.Run("0.0.0.0:9090") }
Gin framework parameter passing
Get form parameters
import ( "github.com/gin-gonic/gin" "net/http" ) type Result struct { Message string `json:"message"` Code int `json:"code"` } type UserInfo struct { Result UserName string `json:"username"` Passwd string `json:"passwd"` } func handleUserInfo(c *gin.Context) { username := c.PostForm("username") passwd := c.PostForm("passwd") var result UserInfo = UserInfo{ Result: Result{ Message: "success", Code: 200, }, UserName: username, Passwd: passwd, } c.JSON(http.StatusOK,result) } func main() { r := gin.Default() r.POST("/user/info",handleUserInfo) r.Run(":9090") }
Single file upload
func handleUpload(c *gin.Context) { file,err := c.FormFile("testfile") if err != nil { fmt.Printf("upload file faild,err:%v\n",err) return } //File upload path filename := fmt.Sprintf("/Users/wanghui/go/src/oldBoy/day8/tmp/%s",file.Filename) //file save err = c.SaveUploadedFile(file,filename) if err != nil { fmt.Printf("save file faild,err:%v\n",err) return } //State return c.JSON(http.StatusOK,"file upload success") } func main() { r := gin.Default() r.POST("/file/upload",handleUpload) r.Run(":9090") }
Multi file upload
func multiHandleUpload(c *gin.Context) { //Multi file upload form,err := c.MultipartForm() if err != nil { fmt.Printf("upload file faild,err:%v\n",err) return } files := form.File["testfile"] for _,file := range files { filename := fmt.Sprintf("/Users/wanghui/go/src/oldBoy/day8/tmp/%s",file.Filename) err = c.SaveUploadedFile(file,filename) if err != nil { fmt.Printf("save file faild,err:%v\n",err) return } } //State return c.JSON(http.StatusOK,"file upload success") } func main() { r := gin.Default() r.POST("/file/upload",handleUpload) r.POST("/files",multiHandleUpload) r.Run(":9090") }
Upload files through postman
Routing packet
func main() { r := gin.Default() v1Group := r.Group("/v1") v1Group.POST("/user/info",handleUserInfo) v1Group.POST("/user/info2",handleUserInfo) r.Run(":9090") }
Parameter binding of gin
- Why use parameter binding
- Through the mechanism of reflection, the parameters such as querystring, form form, json and xml are automatically extracted into struct
- Through the content type in the http protocol, identify whether it is json, xml or form
type UserInfo struct { UserName string `form:"username" json:"username" binding:"required"` Passwd string `form:"passwd" json:"passwd" binding:"required"` Age int `form:"age" json:"age" binding:"required"` Sex string `form:"sex" json:"sex" binding:"required"` } func PostUserInfo(c *gin.Context) { var UserInfo UserInfo //Form binding, using pointers err := c.ShouldBind(&UserInfo) if err != nil { return } c.JSON(http.StatusOK,UserInfo) } func PostUserInfoJson(c *gin.Context) { var UserInfo UserInfo //Form binding, using pointers err := c.ShouldBindJSON(&UserInfo) if err != nil { return } c.JSON(http.StatusOK,UserInfo) } func GetUserInfoJson(c *gin.Context) { var UserInfo UserInfo //Form binding, using pointers err := c.ShouldBindJSON(&UserInfo) if err != nil { return } c.JSON(http.StatusOK,UserInfo) } func main() { r := gin.Default() v1Group := r.Group("/v1") v1Group.POST("/user/infos",PostUserInfo) v1Group.POST("/user/infojson",PostUserInfoJson) v1Group.GET("/user/info",GetUserInfoJson) r.Run(":9090") }
Rendering
- Rendering with gin.Context.JSON method
type UserInfo struct { UserName string `form:"username" json:"username" binding:"required"` Passwd string `form:"passwd" json:"passwd" binding:"required"` } func GetUserInfoJson(c *gin.Context) { var userInfo = &UserInfo{ UserName: "zhansan", Passwd: "aaaa", } c.XML(200,userInfo) } func main() { r := gin.Default() v1Group := r.Group("/v1") v1Group.GET("/user/info",GetUserInfoJson) r.Run(":9090") }
HTML template rendering
- templates/post.html
{{ define "index.tmpl" }} <html><h1> {{ . }} </h1> <p>Using posts/index.tmpl</p> </html> {{ end }}
- server.go
func HandleHtmml(c *gin.Context) { c.HTML(200,"index.tmpl","mmmmmmmm") } func main() { r := gin.Default() r.LoadHTMLGlob("./templates/*") r.GET("/user/info",HandleHtmml) r.Run(":9090") }
gin Middleware
- In the request processing process, the gin framework adds the user's own hook function, which is called middleware
- Therefore, middleware can be used to process some public business logic, such as time-consuming statistics, log printing, login verification, etc
func StatCost(c *gin.Context) { //middleware start := time.Now() fmt.Printf("start \n") c.Next() lattacy := time.Since(start) fmt.Printf("cost Time is %dms\n", lattacy/1000/1000) } func funcHello(c *gin.Context) { fmt.Printf("request start\n") time.Sleep(time.Second * 3) c.JSON(http.StatusOK, "hello world") } func main() { r := gin.Default() r.Use(StatCost) r.GET("/hello", funcHello) r.Run(":9090") }
Routing principle of gin framework
- The routing part uses: https://github.com/julienschmidt/httprouter
- For routing rules, httprouter will construct a prefix tree