最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang中Gin框架的使用入門教程

 更新時間:2022年10月26日 15:11:54   作者:用戶6512516549724  
這篇文章主要為大家詳細介紹了Golang中Gin框架的使用教程,文中通過簡單的示例為大家講解了Gin框架的安裝與使用,感興趣的小伙伴開業(yè)跟隨小編一起學習一下

官方地址: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() // 監(jiān)聽并在 0.0.0.0:8080 上啟動服務
}

然后在瀏覽器中進行測試: http://localhost:8080 就可以訪問到響應的請求。

常見請求與分組請求

下面展示幾種其他 常規(guī) 請求方式

// 下面列出常用幾種請求方式
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

獲取參數 與 參數合法性驗證

獲得query中參數

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")
}

獲得multipart/urlencoded form中的參數

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發(fā)送post請求,即可獲得表單中數據。

模型綁定和參數驗證

基本用法

我們已經見識了x-www-form-urlencoded類型的參數處理,現(xiàn)在越來越多的應用習慣使用JSON來通信,也就是無論返回的response還是提交的request,其content-type類型都是application/json的格式。而對于一些舊的web表單頁還是x-www-form-urlencoded的形式,這就需要我們的服務器能支持住這多種content-type的參數了。

由于go是靜態(tài)語言,需要先實現(xiàn)定義數據模型,這就需要用到gin的model bind功能了。

gin使用go-playground/validator.v8驗證參數,查看完整文檔。

需要在綁定的字段上設置tag,比如,綁定格式為json,需要這樣設置json:"fieldname" 。

此外,Gin還提供了兩套綁定方法:

1.Must bind

  • Methods - Bind, BindJSON, BindXML, BindQuery, BindYAML
  • Behavior - 這些方法底層使用 MustBindWith,如果存在綁定錯誤,請求將被以下指令中止 .

c.AbortWithError(400, err).SetType(ErrorTypeBind),

響應狀態(tài)代碼會被設置為400,請求頭Content-Type被設置為text/plain; charset=utf-8。

注意,如果你試圖在此之后設置響應代碼,將會發(fā)出一個警告 [GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422,如果你希望更好地控制行為,請使用ShouldBind相關的方法

2.Should bind

  • Methods - ShouldBind, ShouldBindJSON, ShouldBindXML, ShouldBindQuery, ShouldBindYAML
  • Behavior - 這些方法底層使用 ShouldBindWith,如果存在綁定錯誤,則返回錯誤,開發(fā)人員可以正確處理請求和錯誤。

當我們使用綁定方法時,Gin會根據Content-Type推斷出使用哪種綁定器,如果你確定你綁定的是什么,你可以使用MustBindWith或者BindingWith。

你還可以給字段指定特定規(guī)則的修飾符,如果一個字段用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,前提是后者必須實現(xiàn)了前者的接口
   // 綜上,這里就是將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 #控制器目錄,按模塊存放控制器(或者叫控制器函數),必要的時候可以繼續(xù)劃分子目錄。 │ ├── food.go │ └── user.go ├── main.go #項目入口,這里負責Gin框架的初始化,注冊路由信息,關聯(lián)控制器函數等。 ├── models #模型目錄,負責項目的數據存儲部分,例如各個模塊的Mysql表的讀寫模型。 │ ├── food.go │ └── user.go ├── static #靜態(tài)資源目錄,包括Js,css,jpg等等,可以通過Gin框架配置,直接讓用戶訪問。 │ ├── css │ ├── images │ └── js ├── logs #日志文件目錄,主要保存項目運行過程中產生的日志。 └── views #視圖模板目錄,存放各個模塊的視圖模板,當然有些項目只有api,是不需要視圖部分,可以忽略這個目錄 └── index.html

Gin框架運行模式

為方便調試,Gin 框架在運行的時候默認是debug模式,在控制臺默認會打印出很多調試日志,上線的時候我們需要關閉debug模式,改為release模式。

設置Gin框架運行模式:

通過環(huán)境變量設置 export GIN_MODE=release

GIN_MODE環(huán)境變量,可以設置為debug或者release

通過代碼設置

在main函數,初始化gin框架的時候執(zhí)行下面代碼
// 設置 release模式
gin.SetMode(gin.ReleaseMode)
// 或者 設置debug模式
gin.SetMode(gin.DebugMode)

Gin如何獲取客戶ip

route.GET("/ip", func(c *gin.Context) {
   // 獲取用戶IP
   ip := c.ClientIP()
   c.JSON(http.StatusBadRequest, gin.H{"ip": ip})
})

Gin處理請求結果

以String類型響應請求

func (c *Context) String(code int, format string, values ...interface{})
c.String(200,"歡迎訪問%s, 你是%s", "tizi360.com!","最靚的仔!")

以Json格式響應請求

我們開發(fā)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")

設置http響應頭

func(c *gin.Context) {
  //設置http響應 header, key/value方式,支持設置多個header
  c.Header("site","tizi365")
}

Gin處理html模板

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")
}

Gin訪問靜態(tài)資源文件

func main() {
    router := gin.Default()
    // 設置靜態(tài)資源文件目錄,并且綁定一個Url前綴
    // 靜態(tài)資源文件目錄:/var/www/tizi365/assets
    // /assets是訪問靜態(tài)資源的url前綴
    // 例如:
    //   /assets/images/1.jpg 這個url文件,存儲在/var/www/tizi365/assets/images/1.jpg
    router.Static("/assets", "/var/www/tizi365/assets")

    // 為單個靜態(tài)資源文件,綁定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")
}

Gin處理Cookie操作

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")
}

Gin文件上傳

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中間件

在Gin框架中,中間件(Middleware)指的是可以攔截http請求-響應生命周期的特殊函數,在請求-響應生命周期中可以注冊多個中間件,每個中間件執(zhí)行不同的功能,一個中間執(zhí)行完再輪到下一個中間件執(zhí)行。

中間件的常見應用場景如下:

  • 請求限速
  • api接口簽名處理
  • 權限校驗
  • 統(tǒng)一錯誤處理

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. 執(zhí)行中間件設置 \n")
      // 在這里處理請求到達控制器函數之前的邏輯

      // 調用下一個中間件,或者控制器處理函數,具體得看注冊了多少個中間件。
      c.Next()
      fmt.Printf("4. 完成 執(zhí)行中間件設置 \n")
      // 在這里可以處理請求返回給用戶之前的邏輯
      latency := time.Since(t)
      log.Print(latency)

      // 例如,查詢請求狀態(tài)嗎
      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. 開始執(zhí)行業(yè)務邏輯 \n")
      example := c.MustGet("example").(string)

      // it would print: "12345"
      log.Println(example)
      fmt.Printf("3. 業(yè)務邏輯執(zhí)行完成 \n")
   })

   // Listen and serve on 0.0.0.0:8080
   r.Run(":8080")
}

其輸出結果如下:

1. 執(zhí)行中間件設置 
2. 開始執(zhí)行業(yè)務邏輯 
2022/10/22 16:33:29 12345
3. 業(yè)務邏輯執(zhí)行完成 
4. 完成 執(zhí)行中間件設置 
2022/10/22 16:33:29 658.681µs
2022/10/22 16:33:29 200

Gin 中間件類似 Node中的洋蔥模型。

以上就是Golang中Gin框架的使用入門教程的詳細內容,更多關于Golang Gin框架的資料請關注腳本之家其它相關文章!

相關文章

  • go語言中的數組指針和指針數組的區(qū)別小結

    go語言中的數組指針和指針數組的區(qū)別小結

    本文主要介紹了go語言中的數組指針和指針數組的區(qū)別小結,文中通過示例代碼介紹的很詳細,具有一定的參考價值,感興趣的可以了解一下
    2024-10-10
  • GO語言支付寶沙箱對接的實現(xiàn)

    GO語言支付寶沙箱對接的實現(xiàn)

    本文介紹了如何使用GO語言對接支付寶沙箱環(huán)境,包括秘鑰生成、SDK安裝和代碼實現(xiàn)等步驟,詳細內容涵蓋了從秘鑰生成到前端代碼的每個階段,為開發(fā)者提供了一條清晰的指引
    2024-09-09
  • 淺談go build后加文件和目錄的區(qū)別

    淺談go build后加文件和目錄的區(qū)別

    這篇文章主要介紹了淺談go build后加文件和目錄的區(qū)別,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • go?defer?return?panic?執(zhí)行順序示例詳解

    go?defer?return?panic?執(zhí)行順序示例詳解

    這篇文章主要介紹了go?defer?return?panic?執(zhí)行順序,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • golang調用shell命令(實時輸出,終止)

    golang調用shell命令(實時輸出,終止)

    本文主要介紹了golang調用shell命令(實時輸出,終止),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • golang限流庫兩個大bug(半年之久無人提起)

    golang限流庫兩個大bug(半年之久無人提起)

    最近我的同事在使用uber-go/ratelimit[1]這個限流庫的時候,遇到了兩個大?bug,這兩個?bug?都是在這個庫的最新版本(v0.3.0)中存在的,而這個版本從?7?月初發(fā)布都已經過半年了,都沒人提?bug,難道大家都沒遇到過么
    2023-12-12
  • 詳解Go語言中make和new的區(qū)別

    詳解Go語言中make和new的區(qū)別

    Go語言中,有兩個比較雷同的內置函數,分別是new和make方法,那他們有什么區(qū)別呢?本文將通過一些示例為大家詳細介紹一下,感興趣的可以了解一下
    2023-02-02
  • logrus hook輸出日志到本地磁盤的操作

    logrus hook輸出日志到本地磁盤的操作

    這篇文章主要介紹了logrus hook輸出日志到本地磁盤的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • Go各時間字符串使用解析

    Go各時間字符串使用解析

    這篇文章主要介紹了Go各時間字符串使用解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • Gin框架中參數校驗優(yōu)化詳解

    Gin框架中參數校驗優(yōu)化詳解

    這篇文章主要為大家詳細介紹了Gin框架中參數校驗優(yōu)化的相關知識,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以了解下
    2023-08-08

最新評論

阿拉善左旗| 田林县| 沙田区| 紫金县| 额尔古纳市| 原阳县| 静宁县| 隆化县| 德阳市| 桓台县| 通州市| 海伦市| 威宁| 珲春市| 木里| 遂平县| 郎溪县| 土默特右旗| 津南区| 澄城县| 老河口市| 阿合奇县| 资溪县| 册亨县| 柘荣县| 镇康县| 准格尔旗| 沙洋县| 慈溪市| 嘉峪关市| 北碚区| 浦江县| 连州市| 康平县| 武隆县| 霍邱县| 都匀市| 嘉祥县| 昆明市| 辉县市| 会理县|