golang gin框架
阿新 • • 發佈:2022-04-18
gin框架使用
1.安裝
go get gopkg.in/gin-gonic/gin.v1
2.簡單的HTTP服務
package main import ( "github.com/gin-gonic/gin" "net/http" ) func main() { // 1.建立一個路由handler,預設帶有 Logger 和 Recovery 兩個中介軟體 engine := gin.Default() // 2.通過HTTP方法繫結路由規則和路由函式 engine.GET("/", func(ctx *gin.Context) { ctx.String(http.StatusOK, "hello world") }) // 3.啟動路由的Run方法監聽埠 engine.Run(":8080") }
3.GET請求的引數獲取
3.1 獲取GET請求路由的引數
(1.) 冒號:加上一個引數名組成路由引數。可以使用c.Params的方法讀取其值。
路由:http://127.0.0.1:8080/user/jone ------------------------------------------------- // 冒號:加上一個引數名組成路由引數,可以獲取到請求引數,請求路徑如:/user/zhangsan engine.GET("/user/:name", func(ctx *gin.Context) { // 使用c.Params的方法讀取其值,型別為string name := ctx.Param("name") ctx.String(http.StatusOK, "hello %s", name) // 輸出:hello jone })
(2.) 除了冒號,gin還提供了星號處理引數,*號能匹配的規則就更多
星號:匹配可有可無,但需保留最後的/,否則會報404,如: http://127.0.0.1:8080/user/jone/ http://127.0.0.1:8080/user/jone/play ------------------------------------------------------------ engine.GET("/user/:name/*action", func(ctx *gin.Context) { // 使用c.Params的方法讀取其值,型別為string name := ctx.Param("name") action := ctx.Param("action") ctx.String(http.StatusOK, "hello %s,action:%s", name, action) // 輸出:hello jone,action:/play })
(3.)GET請求URL中通過key=value的形式,可通過c.Query()獲取
// 請求示例:http://127.0.0.1:8080/welcome?first_name=tom&last_name=lucy
engine.GET("/welcome", func(ctx *gin.Context) {
// 使用c.DefaultQuery方法讀取引數,其中當引數不存在的時候,提供一個預設值
first_name := ctx.DefaultQuery("first_name", "jone")
// 使用Query方法讀取正常引數,當引數不存在的時候,返回空字串
last_name := ctx.Query("last_name")
ctx.String(http.StatusOK, "first_name: %s,last_name: %s", first_name, last_name) // 輸出:first_name: tom,last_name: lucy
})
4.Post請求引數獲取
4.1 form表單資料獲取
// form表單資料獲取,請求示例:
// curl -X POST http://127.0.0.1:8080/form_post -H "Content-Type:application/x-www-form-urlencoded" -d "message=hello&nick=rsj217" | python -m json.tool
------------------------------------------------------------------------
engine.POST("/form_post", func(ctx *gin.Context) {
message := ctx.PostForm("message")
// c.PostFROM解析的是x-www-form-urlencoded或from-data的引數。
nick := ctx.DefaultPostForm("nick", "anonymous")
// 呼叫c.JSON則返回json資料,其中gin.H封裝了生成json的方式
ctx.JSON(http.StatusOK, gin.H{
"status": gin.H{
"status_code": 200,
"status": "ok",
},
"message": message,
"nick": nick,
})
})
4.2 檔案上傳
// 單個檔案上傳,測試:curl -X POST http://127.0.0.1:8000/upload -F "upload=@/Users/ghost/Desktop/pic.jpg" -H "Content-Type: multipart/form-data"
----------------------------------------------------------------------------------
engine.POST("/upload", func(ctx *gin.Context) {
//name := ctx.PostForm("name")
// 使用c.Request.FormFile解析客戶端檔案name屬性
file, header, err := ctx.Request.FormFile("upload")
if err != nil {
ctx.String(http.StatusBadRequest, "bad request")
return
}
// 從header中獲取檔名
fileName := header.Filename
// 建立檔案
out, err := os.Create(fileName)
if err != nil {
ctx.String(http.StatusInternalServerError, "create file failed")
return
}
defer out.Close()
// 使用os的操作,把檔案資料複製到硬碟上
_, err = io.Copy(out, file)
if err != nil {
ctx.String(http.StatusInternalServerError, "io copy failed")
return
}
ctx.String(http.StatusCreated, "upload success")
})
上傳多個檔案:
router.POST("/multi/upload", func(c *gin.Context) {
err := c.Request.ParseMultipartForm(200000)
if err != nil {
log.Fatal(err)
}
// 使用了c.Request.MultipartForm得到檔案控制代碼
formdata := c.Request.MultipartForm
// 獲取檔案資料
files := formdata.File["upload"]
// 遍歷檔案讀寫
for i, _ := range files {
file, err := files[i].Open()
defer file.Close()
if err != nil {
log.Fatal(err)
}
out, err := os.Create(files[i].Filename)
defer out.Close()
if err != nil {
log.Fatal(err)
}
_, err = io.Copy(out, file)
if err != nil {
log.Fatal(err)
}
c.String(http.StatusCreated, "upload successful")
}
})
4.3 資料繫結
(1.)使用ctx.BindJSON()或者ctx.BindWith()
// 資料繫結,測試:curl -X POST http://127.0.0.1:8080/login -H "Content-Type:application/x-www-form-urlencoded" -d "username=jone&password=123&age=21" | python -m json.tool
engine.POST("/login", func(ctx *gin.Context) {
var user User
var err error
contentType := ctx.Request.Header.Get("Content-Type")
switch contentType {
case "application/json":
err = ctx.BindJSON(&user)
case "application/x-www-form-urlencoded":
err = ctx.BindWith(&user, binding.Form)
}
if err != nil {
log.Fatal(err)
}
ctx.JSON(http.StatusOK, gin.H{
"user": user.UserName,
"password": user.Password,
"age": user.Age,
})
})
(2.)使用c.Bind()函式
// 使用c.Bind會根據content-type自動推斷繫結的引數型別
engine.POST("/login2", func(c *gin.Context) {
var user User
err := c.Bind(&user)
if err != nil {
fmt.Println(err)
log.Fatal(err)
}
c.JSON(http.StatusOK, gin.H{
"username": user.UserName,
"password": user.Password,
"age": user.Age,
})
4.4 格式渲染
router.GET("/render", func(c *gin.Context) {
contentType := c.DefaultQuery("content_type", "json")
if contentType == "json" {
// JSON格式渲染
c.JSON(http.StatusOK, gin.H{
"user": "rsj217",
"passwd": "123",
})
} else if contentType == "xml" {
// XML格式渲染
c.XML(http.StatusOK, gin.H{
"user": "rsj217",
"passwd": "123",
})
}
})
4.5 重定向
router.GET("/redict/google", func(c *gin.Context) {
c.Redirect(http.StatusMovedPermanently, "https://google.com")
})
4.6 分組路由
v1 := router.Group("/v1")
v1.GET("/login", func(c *gin.Context) {
c.String(http.StatusOK, "v1 login")
})
v2 := router.Group("/v2")
v2.GET("/login", func(c *gin.Context) {
c.String(http.StatusOK, "v2 login")
})
4.7 中介軟體
(1.) 中介軟體函式
func MiddleWare() gin.HandlerFunc {
return func(c *gin.Context) {
fmt.Println("before middleware")
// 設定請求
c.Set("request", "clinet_request")
c.Next()
fmt.Println("before middleware")
}
}
(2.)中介軟體定義
// 使用中介軟體,呼叫中介軟體函式
router.Use(MiddleWare())
{
router.GET("/middleware", func(c *gin.Context) {
request := c.MustGet("request").(string)
// 獲取請求
req, _ := c.Get("request")
c.JSON(http.StatusOK, gin.H{
"middile_request": request,
"request": req,
})
})
}
(3.)單個路由中介軟體
router.GET("/before", MiddleWare(), func(c *gin.Context) {
request := c.MustGet("request").(string)
c.JSON(http.StatusOK, gin.H{
"middile_request": request,
})
})
// 使用全域性CORS中介軟體。
// router.Use(Cors())
//rate-limit 中介軟體
lmt := tollbooth.NewLimiter(1, nil)
lmt.SetMessage("服務繁忙,請稍後再試...")
(4.) 群組中介軟體
authorized := router.Group("/", MyMiddelware())
// 或者這樣用:
authorized := router.Group("/")
authorized.Use(MyMiddelware())
{
authorized.POST("/login", loginEndpoint)
}
(5.) 使用中介軟體進行介面鑑權
router.GET("/auth/signin", func(c *gin.Context) {
cookie := &http.Cookie{
Name: "session_id",
Value: "123",
Path: "/",
HttpOnly: true,
}
http.SetCookie(c.Writer, cookie)
c.String(http.StatusOK, "Login successful")
})
// 使用中介軟體AuthMiddleWare註冊之後,將會先執行AuthMiddleWare的邏輯,然後才到/home的邏輯
router.GET("/home", AuthMiddleWare(), func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"data": "home"})
})
-----------------------------------------------------------------------
func AuthMiddleWare() gin.HandlerFunc {
return func(c *gin.Context) {
if cookie, err := c.Request.Cookie("session_id"); err == nil {
value := cookie.Value
fmt.Println(value)
if value == "123" {
c.Next()
return
}
}
c.JSON(http.StatusUnauthorized, gin.H{
"error": "Unauthorized",
})
c.Abort()
return
}
}
4.8 自定義router
func main() {
router := gin.Default()
http.ListenAndServe(":8080", router)
}
--------------------------------------------------------
func main() {
router := gin.Default()
// router.Run(":80")
// 這樣寫就可以了,下面所有程式碼(go1.8+)是為了優雅處理重啟等動作。
srv := &http.Server{
Addr: ":80",
Handler: router,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
}
go func() {
// 監聽請求
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()
// 優雅Shutdown(或重啟)服務
quit := make(chan os.Signal)
signal.Notify(quit, os.Interrupt) // syscall.SIGKILL
<-quit
log.Println("Shutdown Server ...")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatal("Server Shutdown:", err)
}
select {
case <-ctx.Done():
}
log.Println("Server exiting")
}
4.9 靜態資源載入
router := gin.Default()
// 靜態資源載入,本例為css,js以及資源圖片
router.StaticFS("/public", http.Dir("D:/tmm/website/static"))
router.StaticFile("/favicon.ico", "./resources/favicon.ico")
// 通過 router.LoadHTMLGlob("website/tpl//") 匯入模板根目錄下所有的檔案
router.LoadHTMLGlob("website/tpl/*/*")
// Listen and serve on 0.0.0.0:80
router.Run(":80")