【Go學習】04-1-Gin框架-路由請求響應參數

【Go學習】04-1-Gin框架

  • 初識框架
    • go流行的web框架
      • Gin
      • iris
      • Beego
      • fiber
    • Gin介紹
    • Gin快速入門
  • 路由
    • RESTful API規范
    • 請求方法
    • URI
      • 靜態url
      • 路徑參數
      • 模糊匹配
    • 處理函數
    • 分組路由
  • 請求參數
    • GET請求參數
      • 普通參數
      • 數組參數
      • map參數
    • POST請求參數
      • 表單參數
      • JSON參數
    • 路徑參數
    • 文件參數
  • 響應
    • 字符串方式
    • JSON方式
    • XML方式
    • 文件方式
    • 設置http響應頭
    • 重定向
    • YAML方式


初識框架

框架是一系列工具的集合,能讓開發變的便捷。

學習框架的目的就是為了提供項目的開發效率,使我們更加專注業務,而不是和業務無關的底層代碼。

go流行的web框架

如果學習過其他語言,可能知道Java用的比較多的是Spring框架,PHP用的比較多的是Laravel,python用的多的是Django,都在各自的語言中具有強大的統治力。

go從誕生之初就帶有濃重的開源屬性,其原生庫已經很強大,即使不依賴框架,也能進行高性能開發,又因為其語言并沒有一定的設計標準,所以較為靈活,也就誕生了眾多的框架,各具有特色,滿足不同的喜好。

Gin

地址:https://github.com/gin-gonic/gin

號稱最快的go語言web框架,目前是go官方的推薦框架(https://go.dev/doc/tutorial/)。

iris

地址:https://github.com/kataras/iris

性能比gin高一些,支持MVC,但這款框架評價不太好,使用上問題較多,近些年很少去選擇使用

Beego

地址:https://github.com/beego/beego

國人開發,最早的go web框架之一,工具集比較完善,性能較差,據傳言作者是php轉行,所以框架帶有濃厚的php特色,早期國內使用的多,目前少有人選擇。

fiber

地址:https://github.com/gofiber/fiber

2020年發布的框架,發展迅速,建立在fasthttp之上,性能目前最高,受Express啟發,比較簡潔,上手較快,和gin類似。

當然還有其他一些框架,但從star數上,以及流行程度上看,gin一騎絕塵,gin的好處在于其簡潔,擴展性,穩定性以及性能都比較出色。

go的框架其實是可以理解為庫,并不是用了某一個框架就不能用別的框架,可以選擇性的使用各個庫中的優秀組件,進行組合

Gin介紹

特性:

  • 快速

    基于 Radix 樹的路由,小內存占用。沒有反射。可預測的 API 性能。

  • 支持中間件

    傳入的 HTTP 請求可以由一系列中間件和最終操作來處理。 例如:Logger,Authorization,GZIP,最終操作 DB。

  • Crash 處理

    Gin 可以 catch 一個發生在 HTTP 請求中的 panic 并 recover 它。這樣,你的服務器將始終可用。例如,你可以向 Sentry 報告這個 panic!

  • JSON 驗證

    Gin 可以解析并驗證請求的 JSON,例如檢查所需值的存在。

  • 路由組

    更好地組織路由。是否需要授權,不同的 API 版本…… 此外,這些組可以無限制地嵌套而不會降低性能。

  • 錯誤管理

    Gin 提供了一種方便的方法來收集 HTTP 請求期間發生的所有錯誤。最終,中間件可以將它們寫入日志文件,數據庫并通過網絡發送。

  • 內置渲染

    Gin 為 JSON,XML 和 HTML 渲染提供了易于使用的 API。

  • 可擴展性

    新建一個中間件非常簡單。

Gin快速入門

go版本需求:go1.13及以上

環境:windows 11

# 創建工作區
F:\Code\Golang\TuLing\workPath>mkdir ginlearn
F:\Code\Golang\TuLing\workPath>cd ginlearn
# 初始化工作區
F:\Code\Golang\TuLing\workPath\ginlearn>go work init# 創建模塊
F:\Code\Golang\TuLing\workPath\ginlearn>mkdir helloworld
F:\Code\Golang\TuLing\workPath\ginlearn>cd helloworld
# 初始化模塊
F:\Code\Golang\TuLing\workPath\ginlearn\helloworld>go mod init test.com/helloworld
go: creating new go.mod: module test.com/helloworld
F:\Code\Golang\TuLing\workPath\ginlearn\helloworld>cd ..# 將模塊加入工作區
F:\Code\Golang\TuLing\workPath\ginlearn>go work use ./helloworld

使用goland打開

在這里插入圖片描述

下載gin

PS F:\Code\Golang\TuLing\workPath\ginlearn> cd .\helloworld\
PS F:\Code\Golang\TuLing\workPath\ginlearn\helloworld> go get -u github.com/gin-gonic/gin

示例程序,創建main.go

package mainimport "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 上啟動服務
}

運行后,apifox進行測試

在這里插入圖片描述

符合預期,這樣簡單的代碼就實現了一個http的服務

路由

路由是URI到函數的映射。

一個URI含: http://localhost:8080/user/find?id=11

  • 協議,比如http,https等
  • ip端口或者域名,比如127.0.0.1:8080或者www.test.com
  • path,比如 /path
  • query,比如 ?query

同時訪問的時候,還需要指明HTTP METHOD,比如

  • GET

    GET方法請求一個指定資源的表示形式. 使用GET的請求應該只被用于獲取數據.

  • POST

    POST方法用于將實體提交到指定的資源,通常會導致在服務器上的狀態變化

  • HEAD

    HEAD方法請求一個與GET請求的響應相同的響應,但沒有響應體.

  • PUT

    PUT方法用請求有效載荷替換目標資源的所有當前表示

  • DELETE

    DELETE方法刪除指定的資源

  • CONNECT

    CONNECT方法建立一個到由目標資源標識的服務器的隧道。

  • OPTIONS

    OPTIONS方法用于描述目標資源的通信選項。

  • TRACE

    TRACE方法沿著到目標資源的路徑執行一個消息環回測試。

  • PATCH

    PATCH方法用于對資源應用部分修改。

使用的時候,應該盡量遵循其語義

RESTful API規范

RESTful API 的規范建議我們使用特定的HTTP方法來對服務器上的資源進行操作。

比如:

  1. GET,表示讀取服務器上的資源
  2. POST,表示在服務器上創建資源
  3. PUT,表示更新或者替換服務器上的資源
  4. DELETE,表示刪除服務器上的資源
  5. PATCH,表示更新/修改資源的一部分

請求方法

r.GET("/get", func(ctx *gin.Context) {ctx.JSON(200, "get")
})
r.POST("/post", func(ctx *gin.Context) {ctx.JSON(200, "post")
})
r.DELETE("/delete", func(ctx *gin.Context) {ctx.JSON(200, "delete")
})
r.PUT("/put", func(ctx *gin.Context) {ctx.JSON(200, "put")
})

如果想要支持所有:

r.Any("/any", func(ctx *gin.Context) {ctx.JSON(200, "any")
})

如果想要支持其中的幾種:

r.GET("/hello", func(ctx *gin.Context) {//數組 map list 結構體ctx.JSON(200, gin.H{"name": "hello world",})
})
r.POST("/hello", func(ctx *gin.Context) {//數組 map list 結構體ctx.JSON(200, gin.H{"name": "hello world",})
})

URI

URI書寫的時候,我們不需要關心scheme和authority這兩部分,我們主要通過path和query兩部分的書寫來進行資源的定位。

靜態url

比如/hello/user/find

r.POST("/user/find", func(ctx *gin.Context) {
})

路徑參數

比如/user/find/:id

r.POST("/user/find/:id", func(ctx *gin.Context) {param := ctx.Param("id")ctx.JSON(200, param)
})

模糊匹配

比如/user/*path

r.POST("/user/*path", func(ctx *gin.Context) {param := ctx.Param("path")ctx.JSON(200, param)
})

處理函數

定義:

type HandlerFunc func(*Context)

通過上下文的參數,獲取http的請求參數,響應http請求等。

分組路由

在進行開發的時候,我們往往要進行模塊的劃分,比如用戶模塊,以user開發,商品模塊,以goods開頭。

或者進行多版本開發,不同版本之間路徑是一致的,這種時候,就可以用到分組路由了。

比如

ug := r.Group("/user")
{ug.GET("find", func(ctx *gin.Context) {ctx.JSON(200, "user find")})ug.POST("save", func(ctx *gin.Context) {ctx.JSON(200, "user save")})
}
gg := r.Group("/goods")
{gg.GET("find", func(ctx *gin.Context) {ctx.JSON(200, "goods find")})gg.POST("save", func(ctx *gin.Context) {ctx.JSON(200, "goods save")})
}

請求路徑則為

[GIN-debug] GET    /user/find                --> main.main.func2 (3 handlers)
[GIN-debug] POST   /user/save                --> main.main.func3 (3 handlers)
[GIN-debug] GET    /goods/find               --> main.main.func4 (3 handlers)
[GIN-debug] POST   /goods/save               --> main.main.func5 (3 handlers)

請求參數

GET請求參數

使用Get請求傳參時,類似于這樣

http://localhost:8080/user/save?id=11&name=zhangsan

如何獲取呢?

普通參數

request url: http://localhost:8080/user/save?id=11&name=zhangsan

  • Query:匹配字段

    r.GET("/user/save", func(ctx *gin.Context) {id := ctx.Query("id")name := ctx.Query("name")ctx.JSON(200, gin.H{"id":   id,"name": name,})
    })
    

    如果參數不存在,就給一個默認值:

  • DefaultQuery:query為空時回返回個默認值

    r.GET("/user/save", func(ctx *gin.Context) {id := ctx.Query("id")name := ctx.Query("name")address := ctx.DefaultQuery("address", "北京")ctx.JSON(200, gin.H{"id":      id,"name":    name,"address": address,})
    })
    
  • GetQuery:多了個query成功與否的返回值

    r.GET("/user/save", func(ctx *gin.Context) {id, ok := ctx.GetQuery("id")address, aok := ctx.GetQuery("address")ctx.JSON(200, gin.H{"id":      id,"idok":    ok,"address": address,"aok":     aok,})
    })
    

    id是數值類型,上述獲取的都是string類型,根據類型獲取:通過form進行字段匹配

  • BindQuery:與結構體字段進行匹配

    type User struct {Id   int64  `form:"id"`Name string `form:"name"`
    }
    r.GET("/user/save", func(ctx *gin.Context) {var user Usererr := ctx.BindQuery(&user)if err != nil {log.Println(err)}ctx.JSON(200, user)
    })
    
  • ShouldBindQuery:有binding字段的要求必填,否則報錯

    r.GET("/user/save", func(ctx *gin.Context) {var user Usererr := ctx.ShouldBindQuery(&user)if err != nil {log.Println(err)}ctx.JSON(200, user)
    })
    

    區別

    當bind是必須的時候,ShouldBindQuery會報錯,開發者自行處理,狀態碼不變。

    type User struct {Id      int64  `form:"id"`Name    string `form:"name"`Address string `form:"address" binding:"required"`
    }
    

    BindQuery則報錯的同時,會將狀態碼改為400。所以一般建議是使用Should開頭的bind。

數組參數

請求url:http://localhost:8080/user/save?address=Beijing&address=shanghai

  • QueryArray:重復查詢字段組裝成數組

    r.GET("/user/save", func(ctx *gin.Context) {address := ctx.QueryArray("address")ctx.JSON(200, address)
    })
    
  • GetQueryArray:多成功與否返回值

    r.GET("/user/save", func(ctx *gin.Context) {address, ok := ctx.GetQueryArray("address")fmt.Println(ok)ctx.JSON(200, address)
    })
    
  • ShouldBindQuery

    r.GET("/user/save", func(ctx *gin.Context) {var user Usererr := ctx.ShouldBindQuery(&user)fmt.Println(err)ctx.JSON(200, user)
    })
    

    但是這樣的話我們的user的address要求就是個數組

    type User struct {Id      int64    `form:"id"`Name    string   `form:"name"`Address []string `form:"address" binding:"required"`
    }
    

    成功返回

    {"Id": 0,"Name": "","Address": ["Beijing","shanghai"]
    }
    

map參數

請求url:http://localhost:8080/user/save?addressMap[home]=Beijing&addressMap[company]=shanghai

  • QueryMap:組裝成map

    r.GET("/user/save", func(ctx *gin.Context) {addressMap := ctx.QueryMap("addressMap")ctx.JSON(200, addressMap)
    })
    
  • GetQueryMap:多成功與否返回值

    r.GET("/user/save", func(ctx *gin.Context) {addressMap, _ := ctx.GetQueryMap("addressMap")ctx.JSON(200, addressMap)
    })
    

    返回值

    {"company": "shanghai","home": "Beijing"
    }
    

POST請求參數

post請求一般是表單參數和json參數

表單參數

r.POST("/user/save", func(ctx *gin.Context) {id := ctx.PostForm("id")name := ctx.PostForm("name")address := ctx.PostFormArray("address")addressMap := ctx.PostFormMap("addressMap")ctx.JSON(200, gin.H{"id":         id,"name":       name,"address":    address,"addressMap": addressMap,})
})
  • PostForm:從表單中對應的字段
  • PostFormArray:從表單找對應的數組
  • PostFormMap:從表單找對應的Map
r.POST("/user/save", func(ctx *gin.Context) {var user Usererr := ctx.ShouldBind(&user)addressMap, _ := ctx.GetPostFormMap("addressMap")user.AddressMap = addressMapfmt.Println(err)ctx.JSON(200, user)
})
  • GetPostFormMap:從表單找對應的Map

JSON參數

json參數如下

{"id":1111,"name":"zhangsan","address": ["beijing","shanghai"],"addressMap":{"home":"beijing"}
}
r.POST("/user/save", func(ctx *gin.Context) {var user Usererr := ctx.ShouldBindJSON(&user)fmt.Println(err)ctx.JSON(200, user)
})

對應字段進行匹配

其他類型參數注入xml,yaml等和json道理一樣

路徑參數

請求url:http://localhost:8080/user/save/111

r.POST("/user/save/:id", func(ctx *gin.Context) {ctx.JSON(200, ctx.Param("id"))
})
  • :id 表示 占位符,可以匹配 任意路徑中的值

  • ctx.Param("id") 用于 獲取路徑參數 id 的值

文件參數

r.POST("/user/save", func(ctx *gin.Context) {form, err := ctx.MultipartForm()if err != nil {log.Println(err)}files := form.Filefor _, fileArray := range files {for _, v := range fileArray {ctx.SaveUploadedFile(v, "./"+v.Filename)}}ctx.JSON(200, form.Value)
})

在form表單中請求file類型

在這里插入圖片描述

這樣就能在本地看到了

在這里插入圖片描述

響應

字符串方式

r.GET("/user/save", func(ctx *gin.Context) {ctx.String(http.StatusOK, "this is a %s", "ms string response")
})

JSON方式

r.GET("/user/save", func(ctx *gin.Context) {ctx.JSON(http.StatusOK, gin.H{"success": true,})
})

XML方式

r.GET("/user/save", func(ctx *gin.Context) {u := XmlUser{Id:   11,Name: "zhangsan",}ctx.XML(http.StatusOK, u)
})

文件方式

r.GET("/user/save", func(ctx *gin.Context) {//ctx.File("./1.png")ctx.FileAttachment("./1.png", "2.png")
})

設置http響應頭

r.GET("/user/save", func(ctx *gin.Context) {ctx.Header("test", "headertest")
})

重定向

r.GET("/user/save", func(ctx *gin.Context) {ctx.Redirect(http.StatusMovedPermanently, "http://www.baidu.com")
})

YAML方式

r.GET("/user/save", func(ctx *gin.Context) {ctx.YAML(200, gin.H{"name": "ms", "age": 19})
})

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/897795.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/897795.shtml
英文地址,請注明出處:http://en.pswp.cn/news/897795.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

哈爾濱算力服務器托管推薦-青蛙云

哈爾濱年平均氣溫3.5攝氏度,有發展云計算和算力數據中心的天然優勢 ,今天為哈爾濱算力服務器托管服務商:青蛙云,黑龍江經營17年的老牌IDC服務商。 先來了解下算力服務器: 算力服務器,尤其是那些用于運行人…

【C++】每日一練(有效的括號)

本篇博客給大家帶來的是用C語言來解答有效的括號! 🐟🐟文章專欄:每日一練 🚀🚀若有問題評論區下討論,我會及時回答 ??歡迎大家點贊、收藏、分享! 今日思想:不服輸的少年…

Embedding模型到底是什么?

嵌入模型(Embedding Model)是一種將高維數據映射到低維空間的工具,廣泛應用于自然語言處理(NLP)、推薦系統和圖像識別等領域。它的核心目標是將復雜的數據(如文本、圖像或用戶行為)轉換為稠密的…

Centos離線安裝perl

文章目錄 Centos離線安裝perl1. perl是什么?2. Centos下載地址?3. perl的安裝4. 安裝結果驗證 Centos離線安裝perl 1. perl是什么? Perl 是一種 高級腳本語言,誕生于 1987 年,以強大的 文本處理能力 和靈活性著稱&…

快速學習Bootstrap前端框架

什么是 Bootstrap? Bootstrap 是一個開源的前端框架,用于快速開發響應式(Responsive)和美觀的網頁。它包含: ? HTML 組件(導航欄、按鈕、表單等) ? CSS 樣式(網格系統、排版、顏色等) ? JavaScript 交互(模態框、輪播圖、工具提示等) 官網:Bootstrap The mo…

51單片機的keil c51軟件安裝教程

Keil(C51)介紹、下載、安裝與注冊_keil c51-CSDN博客 參考 安裝 不一定是這個大小,也可以下載別的版本KEID C51 注冊 加入芯片型號 …

DeepIn Wps 字體缺失問題

系統缺失字體 Symbol 、Wingdings 、Wingdings2、Wingdings3、MT—extra 字體問題 問了下DeepSeek 在應用商店安裝或者在windows 里面找 裝了一個GB-18030 還是不行 在windows里面復制了缺失的字體 將字體復制到DeepIn 的字體目錄(Ubuntu 應該也是這個目錄&am…

chebykan閱讀收尾

sciml SciML 是 科學機器學習 (Scientific Machine Learning) 的縮寫,它指的是將機器學習方法應用于解決科學問題,例如物理、化學、生物學等領域中的問題。SciML 旨在利用機器學習的強大能力來提高科學計算的效率和準確性。 SciML 的主要問題: 數據獲取…

SpringBoot使用Logback日志框架與綜合實例

日志框架的使用,系列文章: 《SpringBoot使用Logback日志框架與綜合實例》 《SpringBoot使用@Slf4j注解實現日志輸出》 《Log4j2日志記錄框架的使用教程與簡單實例》 《SpringBoot使用AspectJ實現AOP記錄接口:請求日志、響應日志、異常日志》 《SpringBoot使用AspectJ的@Arou…

【性能測試】Jmeter詳細操作-小白使用手冊(2)

本篇文章主要介紹Jmeter中如何使用 JSON斷言、同步定時器、事務控制器、CSV數據文件設置、HTTP Cookie管理器 目錄 一:JSON斷言 1:正確結果展示 2:錯誤結果展示 3:JSON配置 (1)Additionally assert …

分布式鎖—Redisson的同步器組件

1.Redisson的分布式鎖簡單總結 Redisson分布式鎖包括:可重入鎖、公平鎖、聯鎖、紅鎖、讀寫鎖。 (1)可重入鎖RedissonLock 非公平鎖,最基礎的分布式鎖,最常用的鎖。 (2)公平鎖RedissonFairLock 各個客戶端嘗試獲取鎖時會排隊,按照隊…

國產編輯器EverEdit - 腳本(解鎖文本編輯的無限可能)

1 腳本 1.1 應用場景 腳本是一種功能擴展代碼,用于提供一些編輯器通用功能提供不了的功能,幫助用戶在特定工作場景下提高工作效率,幾乎所有主流的編輯器、IDE都支持腳本。 ??EverEdit的腳本支持js(語法與javascript類似)、VBScript兩種編程…

服務器上的nginx因漏洞掃描需要升級

前言 最近客戶聯系說nginx存在安全漏洞 F5 Nginx 安全漏洞(CVE-2024-7347) F5Nginx是美國F5公司的一款輕量級Web服務器/反向代理服務器及電子郵件(IMAP/POP3)代理服務器,在BSD-like協議下發行。F5 Nginx存在安全漏洞,該漏洞源于可能允許攻擊者使用特制的…

ASP.NET CORE MVC EF框架

1.一個視圖中的多個表單Form中的變量。 方式一:視圖中跨Form變量不能用,得各自定義變量否則編譯不能通過。變量名還不能相同。 或者方式二:在Form之外定義變量 {ViewData["Title"] "ExpenseForm"; }  {L…

【MySQL 中 `TINYINT` 類型與布爾值的關系】

MySQL 中 TINYINT 類型與布爾值的關系 在 MySQL 數據庫中,BOOLEAN 類型并不存在,BOOLEAN 或 BOOL 都是 TINYINT(1) 的別名。通常,TINYINT(1) 類型用于存儲布爾值。 1. TINYINT 類型介紹 TINYINT 是一個占用 1 字節的整數類型,取…

【Rust基礎】Rust后端開發常用庫

使用Rust有一段時間了,期間嘗試過使用Rust做后端開發、命令行工具開發,以及做端側模型部署,也嘗試過交叉編譯、FFI調用等,也算是基本入門了。在用Rust做后端接口開發時,常常會找不到一些合適庫,而這些庫在J…

[leetcode]位運算

一.AND &運算 注:兩個操作數做&運算結果是不會變大的 二.OR |運算 注:兩個操作數做|運算結果是不會變小的 三.XOR(異或) ^運算 注:結果可能變大也可能變小也可能不變,但是不會導致進位,比如兩個四位的數字做…

常見FUZZ姿勢與工具實戰:從未知目錄到備份文件漏洞挖掘

本文僅供學習交流使用,嚴禁用于非法用途。未經授權,禁止對任何網站或系統進行未授權的測試或攻擊。因使用本文所述技術造成的任何后果,由使用者自行承擔。請嚴格遵守《網絡安全法》及相關法律法規! 目錄 本文僅供學習交流使用&am…

前置機跟服務器的關系

在復雜的IT系統架構中,前置機與服務器的協同配合是保障業務高效、安全運行的關鍵。兩者的關系既非簡單的上下級,也非獨立個體,而是通過功能分層與職責分工,構建起一套既能應對高并發壓力、又能抵御安全風險的彈性體系。 在當今復…

MySQL中有哪些索引

1,B-Tree索引:常見的索引類型 2,哈希索引:基于哈希表實現,只支持等值查詢 ,只有Memory存儲引擎和NDB Cluster存儲引擎顯示支持哈希索引 3,全文索引:可在字符列上創建(T…