gin,今天再喝一杯吧。
因為我們的目標是網頁伺服器,果不其然的要從網頁開始講起。
HTTP Method 分成了八種GET
、POST
、DELETE
、PUT
、HEAD
、TRACE
、CONNECT
、OPTIONS
,但在這我們只會簡介常用的GET
跟POST
。
GET
:參數都放在網址裡,很不安全(要是參數是登入時的帳號、密碼,就會容易外洩),但方便開發的時候測試。POST
:參數不在網址裡,比較安全的作法。Json
(JavaScript Object Notation) 是一種資料格式,由各種 陣列(Array)
以及鍵值(Key-Value)
所組成的結構話格式。
[]
是陣列形式,裡面可以放各種物件
{}
是鍵值形式,裡面可以放各種物件
兩種形式可以交錯使用,你中有我我中有你
以下使用gin不同的兩種方式(Context.Data
,Context.JSON
)來達成 返回json資料格式的效果:
func main() {
router := gin.Default()
router.GET("/json", returnJson)
router.GET("/json2", returnJson2)
router.Run(":80")
}
func returnJson(c *gin.Context) {
m := map[string]string{"status": "ok"}
j, _ := json.Marshal(m)
c.Data(http.StatusOK, "application/json", j)
}
func returnJson2(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"狀態": "ok",
})
}
(在這推薦安裝Chrome擴充套件 JSON Viewer Pro
或其他款可以在瀏覽器上方便看json
檔案的套件,畫面看起來更舒適)
另外,可以透過Chrome開發者工具 看到Content-Type
為剛剛所設定的application/json
可以直接在struct
中加入json tag
,讓gin返回json
格式的時候自動對應轉換。
(當然也有支援xml
等格式,甚至可以自訂格式)
func returnJson3(c *gin.Context) {
type Result struct {
Status string `json:"status"`
Message string `json:"message"`
}
var result = Result{
Status: "OK",
Message: "This is Json",
}
c.JSON(http.StatusOK, result)
}
記得 struct中的 Status、Message要字首大寫,要對外暴露給gin套件取用
GET Method
是以網址帶參數的方式進行參數傳遞,可分成以下兩種:
查詢參數(Query Params)
路徑參數(Path Params)
127.0.0.1?
user
=id
參數名稱為user
其中的id
就是使用者的ID。127.0.0.1?user=Jack
為什麼叫作查詢參數、或稱作Query String呢?
因為他使用?
問號來 Query參數
能以這方法夾帶表單參數(HTML Form),但傳遞表單時使用POST方法更為安全。
func main() {
router := gin.Default()
router.GET("/para1", para1)
router.Run(":80")
}
func para1(c *gin.Context) {
// input := c.DefaultQuery("input", "使用者沒有任何輸入。") // 使用者沒有輸入參數時 可設定預設值
input := c.Query("input")
msg := []byte("您輸入的文字為: \n" + input) // 純文字(text/plain)中的換行是\n,網頁格式(html)中的換行才是<br />
c.Data(http.StatusOK, "text/plain; charset=utf-8;", msg) // 如果沒有指定文字編碼、拿掉`charset=utf-8;`的話,中文會變亂碼。
}
成功執行的話,點開後會出現以下結果:
http://127.0.0.1/para1?input=%E5%93%88%E5%93%88%E6%98%AF%E6%88%91%E5%95%A6
路徑即是參數,能以這種方式夾帶參數:
127.0.0.1/
user
/id
其中的user
是參數名稱,可代表使用者頁面,
id
就是使用者的ID。127.0.0.1/user/Jack
func main() {
router := gin.Default()
router.GET("/para2/:input", para2)
router.Run(":80")
}
func para2(c *gin.Context) {
msg := c.Param("input")
c.String(http.StatusOK, "您輸入的文字為: \n%s", msg) // 也可使用 `c.String`返回。第二個參數為組合樣式format
// c.String(http.StatusOK, msg) // 如果沒有組合樣式,可直接輸入字串
}
成功執行的話,點開後會出現以下結果:
http://127.0.0.1/para2/%E5%93%88%E5%93%88%E6%98%AF%E6%88%91%E5%95%A6
post
有寄信、發布訊息的意思
func main() {
router := gin.Default()
router.RedirectFixedPath = true
router.POST("/post", post)
router.Run(":80")
}
func post(c *gin.Context) {
//msg := c.PostForm("input")
msg := c.DefaultPostForm("input", "表單沒有input。") // 沒有輸入參數時 可設定預設值
c.String(http.StatusOK, "您輸入的文字為: \n%s", msg)
}
由於POST Method
參數都隱藏起來了,並非像GET
在網址列填入參數就能達到目的,
開瀏覽器難以測試。在這邊我們會使用到Postman工具來做測試。
測試時選擇POST方法
選擇Body
,格式選擇form-data
,
並且填入表單的Key、Value
router.Any
是任何方法都能夠 handle 的。
Any registers a route that matches all the HTTP methods.
包含 GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE.
func main() {
router := gin.Default()
router.Any("/any", any)
router.Run(":80")
}
func any(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"status": "ok",
})
}
gin預設是**大小寫敏感(case sensitivity)**的,只要對應的URI
字符大小寫不同即視為不同,
這在一些使用情境下非常的不便。
加上這行 重導向正確的URI,讓大小寫通吃。
router.RedirectFixedPath = true