golang-gin包

文章目錄

  • 一、了解gin
  • 二、html渲染
  • 三、gin中get/post獲取值
  • 四、路由分組
  • 五、中間件
  • 六、文件上傳
  • 七、gin中的cookie

一、了解gin

Gin 是一個用 Golang編寫的 高性能的web 框架, 由于http路由的優化,速度提高了近 40 倍。 Gin的特

點就是封裝優雅、API友好。

特性類別具體說明
性能表現基于 Radix 樹實現路由,匹配速度極快,性能接近原生 Go HTTP 服務器
API 設計接口簡潔直觀,學習成本低,如 gin.Default() 快速創建實例,GET() / POST() 注冊路由
中間件支持內置日志、恢復 panic、靜態文件服務等中間件,支持自定義中間件實現擴展功能
路由管理支持路由分組(Group),便于按模塊 / 版本 / 權限組織路由(如 /v1/*/admin/*
參數處理提供便捷的請求參數綁定(ShouldBind),支持 JSON / 表單 / Query 等格式,可配合標簽驗證
數據響應內置高效 JSON 處理,c.JSON() 快速返回 JSON 響應,性能優于標準庫
錯誤處理簡化異常處理流程,c.AbortWithError() 等方法可快速返回結構化錯誤響應
模板渲染集成 HTML 模板引擎,支持模板繼承、自定義函數,適合傳統 Web 應用開發
擴展性設計靈活,易于與 ORM、緩存、認證等工具集成,生態豐富
輕量特性核心代碼簡潔,依賴少,編譯后二進制體積小,適合微服務或輕量應用

下載gin包

go get -u github.com/gin-gonic/gin

測試一下

package main
import "github.com/gin-gonic/gin"
func main() {router := gin.Default()router.GET("/", func(c *gin.Context) {c.JSON(200, map[string]interface{}{"name": "彪子","age": 15,})})router.Run(":8080") // 不寫默認,8080,監聽并在 0.0.0.0:8080 上啟動服務
}

①返回字符串

package main
import "github.com/gin-gonic/gin"
func main() {router := gin.Default()// 類似printf的寫法router.GET("/", func(c *gin.Context) {c.String(200, "我的值為:%v", "啊啊啊")})router.Run(":8080") // 不寫默認,8080,監聽并在 0.0.0.0:8080 上啟動服務
}

②返回json

package main
import "github.com/gin-gonic/gin"
func main() {router := gin.Default()router.GET("/", func(c *gin.Context) {c.JSON(200, map[string]interface{}{"name": "彪子","age": 15,})})router.Run(":8080") // 不寫默認,8080,監聽并在 0.0.0.0:8080 上啟動服務
}

或者可以將map類型用gin自帶的,和我們寫的一樣

router.GET("/", func(c *gin.Context) {c.JSON(200,gin.H{"name": "彪子","age": 15,})})

也可以使用結構體

package main
import ("github.com/gin-gonic/gin"
)
type Ariticle struct {Title stringContent string
}
func main() {router := gin.Default()router.LoadHTMLGlob("templates/*") //配置模板文件router.GET("/", func(c *gin.Context) {article := &Ariticle{Title: "這是標題",Content: "這是內容",}c.JSON(200, article)})router.Run(":8080") // 不寫默認,8080,監聽并在 0.0.0.0:8080 上啟動服務
}

二、html渲染

除了上訴的返回字符串和json數據,我們也可以渲染html。

在這里插入圖片描述

如果模板目錄下存在多個目錄,每個目錄下含有不同的html文件,那么我們這樣操作

在這里插入圖片描述

在html定義值

{{ $title := .Title }}
<h1>{{ $title }}</h1>
{{ $sum := 10 + 20 }}
<p>總和:{{ $sum }}</p>

注釋

{{/* 這是模板注釋,瀏覽器中看不到 */}}

條件判斷

{{ if .IsLogin }}
<p>歡迎回來,{{ .Username }}</p>
{{ else }}
<a href="/login">請登錄</a>
{{ end }}
<!-- 否定判斷 -->
{{ if not .IsEmpty }}
<p>內容不為空</p>
{{ end }}

循環遍歷

<!-- 遍歷切片/數組 -->
<ul>
{{ range .Items }}<li>{{ . }}</li> <!-- 內部的 . 代表當前元素 -->
{{ end }}
</ul><!-- 帶索引的遍歷 -->
<!-- 使用 {{ . }} 時注意上下文變化(如在 range 內部,. 代表當前元素) -->
{{ range $index, $item := .Items }}<p>{{ $index }}: {{ $item.Name }}</p>
{{ end }}<!-- 遍歷映射 -->
{{ range $key, $value := .UserInfo }}<p>{{ $key }}: {{ $value }}</p>
{{ end }}<!-- 空集合處理 -->
{{ range .Items }}<li>{{ . }}</li>
{{ else }}<p>沒有數據</p> <!-- 當集合為空時執行 -->
{{ end }}

原始html輸出

<!-- 假設 .Content 包含 <strong>文本</strong> -->
{{ .Content }} <!-- 輸出:&lt;strong&gt;文本&lt;/strong&gt; -->
{{ .Content | safeHTML }} <!-- 輸出:<strong>文本</strong> -->

三、gin中get/post獲取值

get請求

name:=c.Query("name")
age:=c.DefaultQuery("age","18")

post請求

name := c.PostForm("name")
age := c.DefaultPostForm("age", "18") // 默認值為string類型

將get/post請求的值綁定都按結構體

package mainimport ("net/http""github.com/gin-gonic/gin"
)
// 定義接收參數的結構體
type UserQuery struct {// form標簽指定對應的查詢參數名Name string `form:"name"`Page int `form:"page" binding:"default=1"` // 默認值1
}
func main() {r := gin.Default()// 注冊路由r.GET("/user", func(c *gin.Context) {var query UserQuery// 綁定GET請求參數到結構體if err := c.ShouldBindQuery(&query); err == nil {// 綁定成功,使用參數c.JSON(http.StatusOK, query)return}})// 啟動服務r.Run(":8080")
}

動態路由傳值

package mainimport ("net/http""github.com/gin-gonic/gin"
)
func main() {r := gin.Default()// 注冊路由r.GET("/:uid", func(c *gin.Context) {uid:=c.Param("uid")// 綁定GET請求參數到結構體c.String(http.StatusOK, "uid: %s", uid)})// 啟動服務r.Run(":8080")
}

四、路由分組

package mainimport ("net/http""github.com/gin-gonic/gin"
)
func main() {r := gin.Default()// 1. 基礎路由分組 - 添加路徑前綴userGroup := r.Group("/user"){// 實際路徑: /useruserGroup.GET("", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "用戶列表"})})// 實際路徑: /user/:iduserGroup.GET("/:id", func(c *gin.Context) {id := c.Param("id")c.JSON(http.StatusOK, gin.H{"message": "查看用戶", "id": id})})// 實際路徑: /user/createuserGroup.POST("/create", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "創建用戶"})})}// 2. 帶中間件的路由分組// 創建需要身份驗證的路由分組authGroup := r.Group("/admin")// 為該分組添加中間件(如身份驗證)authGroup.Use(AuthMiddleware()){// 實際路徑: /admin/dashboard,訪問前會經過AuthMiddleware驗證authGroup.GET("/dashboard", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "管理員面板"})})// 實際路徑: /admin/settingsauthGroup.GET("/settings", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "系統設置"})})}// 3. 嵌套路由分組v1 := r.Group("/api/v1"){// 嵌套用戶分組,實際路徑: /api/v1/usersusers := v1.Group("/users"){users.GET("", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "API v1 用戶列表"})})}// 嵌套文章分組,實際路徑: /api/v1/articlesarticles := v1.Group("/articles"){articles.GET("", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "API v1 文章列表"})})}}r.Run(":8080")
}
// 定義一個身份驗證中間件示例
func AuthMiddleware() gin.HandlerFunc {return func(c *gin.Context) {// 實際應用中這里會驗證token或sessiontoken := c.GetHeader("Authorization")if token == "" {c.JSON(http.StatusUnauthorized, gin.H{"error": "未授權訪問"})c.Abort() // 終止請求處理鏈return}// 驗證通過,繼續處理請求c.Next()}
}

如果把不同路由放到不同文件

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

五、中間件

在這里插入圖片描述

c.Next() 的核心作用

流程控制:在中間件中調用 c.Next() 會暫停當前中間件的執行,先執行后續的中間件或路由處理器。

前后置操作: c.Next() 調用前的代碼可以視為 “前置操作”(如權限驗證、日志記錄開始),調用后的代碼可以視為 “后置操作”(如日志記錄結束、響應處理)。

在這里插入圖片描述

全局中間件:可以使后續的所有請求都走此中間件

func main() {r := gin.Default()r.Use(mid1, mid2)// 實際路徑: /userr.GET("/", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "成功"})})r.Run(":8080")
}

在分組路由后配置中間件的兩種方式

// 方式1
a:=r.Group("admin",mid1, mid2)
// 方式2
a:=r.Group("admin")
a.Use(mid1, mid2)

在不同中間件傳遞值

在這里插入圖片描述

gin中間件中使用grountine

在這里插入圖片描述

六、文件上傳

單個文件上傳

package mainimport ("net/http""os""path/filepath""github.com/gin-gonic/gin"
)func main() {r := gin.Default()// 單個文件上傳r.POST("/upload", func(c *gin.Context) {// 獲取上傳的文件file, err := c.FormFile("file")if err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": "獲取文件失敗: " + err.Error(),})return}// 定義保存路徑(當前目錄下的uploads文件夾)savePath := "./uploads"// 確保保存目錄存在if err := ensureDir(savePath); err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "創建保存目錄失敗: " + err.Error(),})return}// 構建完整的保存路徑(目錄+文件名)dst := filepath.Join(savePath, file.Filename)// 使用SaveUploadedFile保存文件if err := c.SaveUploadedFile(file, dst); err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "保存文件失敗: " + err.Error(),})return}c.JSON(http.StatusOK, gin.H{"message":  "文件上傳成功","filename": file.Filename,"savePath": dst,})})r.Run(":8080")
}// 確保目錄存在,不存在則創建
func ensureDir(dir string) error {if _, err := os.Stat(dir); os.IsNotExist(err) {return os.MkdirAll(dir, 0755)}return nil
}

多文件上傳

package mainimport ("net/http""os""path/filepath""github.com/gin-gonic/gin"
)func main() {r := gin.Default()// 多個文件上傳r.POST("/upload-multiple", func(c *gin.Context) {// 解析多部分表單form, err := c.MultipartForm()if err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": "解析表單失敗: " + err.Error(),})return}// 獲取所有名為"file"的文件files := form.File["file"]if len(files) == 0 {c.JSON(http.StatusBadRequest, gin.H{"error": "未找到上傳的文件",})return}// 定義保存路徑savePath := "./uploads"if err := ensureDir(savePath); err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "創建保存目錄失敗: " + err.Error(),})return}// 保存所有文件uploadedFiles := make([]string, 0, len(files))for _, file := range files {dst := filepath.Join(savePath, file.Filename)if err := c.SaveUploadedFile(file, dst); err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "保存文件 " + file.Filename + " 失敗: " + err.Error(),})return}uploadedFiles = append(uploadedFiles, file.Filename)}c.JSON(http.StatusOK, gin.H{"message":   "所有文件上傳成功","fileCount": len(uploadedFiles),"filenames": uploadedFiles,})})r.Run(":8080")
}// 確保目錄存在,不存在則創建
func ensureDir(dir string) error {if _, err := os.Stat(dir); os.IsNotExist(err) {return os.MkdirAll(dir, 0755)}return nil
}

七、gin中的cookie

package mainimport ("net/http""strings""github.com/gin-gonic/gin"
)func main() {r := gin.Default()// 設置Cookier.GET("/set_cookie", func(c *gin.Context) {// 設置一個名為"username",值為"JohnDoe",1小時后過期的Cookiec.SetCookie("username", "JohnDoe", 3600, "/", "example.com", false, true)c.JSON(http.StatusOK, gin.H{"message": "Cookie set successfully"})})// 獲取 Cookier.GET("/get_cookie", func(c *gin.Context) {cookie, err := c.Cookie("username")if err != nil {c.JSON(http.StatusOK, gin.H{"message": "Cookie not found", "error": err.Error()})return}c.JSON(http.StatusOK, gin.H{"message": "Cookie retrieved successfully", "username": cookie})})//刪除 Cookier.GET("/delete_cookie", func(c *gin.Context) {// 將過期時間設置為1小時前,以達到刪除Cookie的效果c.SetCookie("username", "", -3600, "/", "example.com", false, true)c.JSON(http.StatusOK, gin.H{"message": "Cookie deleted successfully"})})// 遍歷Cookier.GET("/list_cookies", func(c *gin.Context) {cookies := c.Request.Cookies()var cookieList []stringfor _, cookie := range cookies {cookieList = append(cookieList, cookie.Name+"="+cookie.Value)}c.JSON(http.StatusOK, gin.H{"message": "List of cookies", "cookies": strings.Join(cookieList, ", ")})})r.Run(":8080")
}

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

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

相關文章

基于腳手架微服務的視頻點播系統-界面布局部分(二):用戶界面及系統管理界面布局

基于腳手架微服務的視頻點播系統-界面布局部分:二.首頁及播放界面布局一.用戶界面布局1.1用戶界面布局分析與實現1.2更新用戶圖像按鈕及邏輯1.3修改按鈕及邏輯1.4上傳視頻對話框實現邏輯1.4.1頁面跳轉邏輯處理1.4.2頁面控件響應處理二.系統界面布局2.1系統管理頁框架2.2審核管理…

STL庫——二叉搜索樹

? ? ? ? ? づ?ど &#x1f389; 歡迎點贊支持&#x1f389; 個人主頁&#xff1a;勵志不掉頭發的內向程序員&#xff1b; 專欄主頁&#xff1a;C語言&#xff1b; 文章目錄 前言 一、二叉搜索樹的概念 二、二叉搜索樹的性能分析 三、二叉搜索樹的插入 四、二叉搜索樹的查…

【Linux】線程概念與控制

一. 線程的概念1.什么是線程線程是進程內部的一個執行流&#xff0c;是進程調度的基本單位。它具有輕量的特點&#xff0c;它的創建和銷毀所消耗的資源更少&#xff0c;線程間切換比進程間切換消耗的資源更少&#xff1b;它與進程共享一張虛擬地址空間表&#xff0c;通過進程來…

雙軸傾角傳感器廠家與物聯網角度傳感器應用全解析

本文主要探討雙軸傾角傳感器廠家的核心技術優勢&#xff0c;以及物聯網角度傳感器在智能監測中的創新應用。同時&#xff0c;也詳細介紹了水平監測傳感器廠家的解決方案特點&#xff0c;并分析了專業進口傾角傳感器代理所提供的原廠品質保障與本地化服務支持。以深圳瑞慣科技有…

容器-資源隔離機制

一. 引言&#xff1a; 大家都知道&#xff0c;在一臺機器上&#xff0c;可以運行任意(根據系統資源)個容器實例。且各容器間是相互獨立&#xff0c;不做任何關聯的。那么&#xff0c;docker是通過什么方式來實現容器隔離的呢&#xff1f; 接下來我們了解下。 二. 關于容器隔離…

Agentic RL Survey: 從被動生成到自主決策

Agentic RL Survey: 從被動生成到自主決策 本文將系統解讀《The Landscape of Agentic Reinforcement Learning for LLMs: A Survey》這篇綜述。該綜述首次將智能體強化學習&#xff08;Agentic RL&#xff09;與傳統LLM-RL范式正式區分&#xff0c;通過MDP/POMDP理論框架梳理…

徹底禁用 CentOS 7.9 中 vi/vim 的滴滴聲

在 VMware 虛擬機中安裝的 CentOS 7.9 系統&#xff0c;即使通過修改 /etc/inputrc 禁用了終端鈴聲&#xff08;set bell-style none&#xff09;&#xff0c;vi 或 vim 編輯時仍可能發出滴滴聲。這是因為 vi/vim 有自己獨立的鈴聲控制機制。以下是解決方法&#xff1a;方法 1&…

基于A2A和ADK的內容規劃代理

項目概述 Content Planner Agent 是一個基于 Google Agent Development Kit (ADK) 和 Python A2A SDK 構建的智能內容規劃代理。該代理能夠根據高層次的內容描述&#xff0c;創建詳細的內容大綱。 什么是A2A Protocol A2A Protocol&#xff08;Agent2Agent 協議&#xff09;…

Linux-條件變量

文章目錄條件變量概述條件變量的優缺點條件變量相關函數pthread_cond_init函數pthread_cond_destroy函數pthread_cond_wait函數pthread_cond_signal函數測試生產者和消費者模型條件變量 概述 與互斥鎖不同&#xff0c;條件變量是用來等待而不是用來上鎖的&#xff0c;條件變量…

[硬件電路-166]:Multisim - SPICE與Verilog語言的區別

SPICE與Verilog語言在電子設計領域中扮演不同角色&#xff0c;SPICE是電路仿真語言&#xff0c;用于精確模擬電路行為&#xff1b;Verilog是硬件描述語言&#xff0c;用于描述數字電路的結構和行為。以下是兩者的詳細區別&#xff1a;一、核心定位與用途SPICE&#xff1a;電路仿…

玩轉Docker | 使用Docker部署Umbrel操作系統

玩轉Docker | 使用Docker部署Umbrel操作系統 前言 一、 Umbrel 介紹 Umbrel簡介 Umbrel主要特點 二、系統要求 環境要求 環境檢查 Docker版本檢查 檢查操作系統版本 三、部署Umbrel服務 下載Umbrel鏡像 編輯部署文件 創建容器 檢查容器狀態 檢查服務端口 安全設置 四、訪問Umbr…

Flink Task線程處理模型:Mailbox

Task的線程 和 MailboxProcessor 的綁定executingThread 是 Task 類&#xff08;StreamTask 的父類&#xff09;在構造時創建的物理線程。MailboxProcessor 是 StreamTask 用來處理異步事件和驅動其主要處理邏輯&#xff08;processInput&#xff09;的核心組件。它們之間的綁定…

OpenCV 銀行卡號識別

目錄 一、項目原理與核心技術 二、環境準備與工具包導入 1. 環境依賴 2. 工具包導入 三、自定義工具類 myutils.py 實現 四、主程序核心流程&#xff08;銀行卡識別.py&#xff09; 1. 命令行參數設置 2. 銀行卡類型映射 3. 輔助函數&#xff1a;圖像展示 五、步驟 1…

計算機二級Python

一.靜態語言和腳本語言高級語言根據計算機執行機制的不同分為兩類&#xff1a;靜態語言和腳本語言靜態語言的核心特征&#xff1a;變量的類型在編譯時&#xff08;寫代碼時&#xff09;就必須確定并固定下來&#xff0c;即在使用一個變量前必須顯式地聲明它地類型一旦聲明&…

Mybatis Log Plugin打印日志,會導致CPU升高卡死

原因 大量日志輸出:MyBatis Log Plugin 會打印大量的 SQL 日志,包括 SQL 語句及其參數。如果項目中 SQL 查詢頻繁且復雜,日志量會非常大,導致 CPU 使用率升高,甚至卡死。 日志級別設置不當:如果將日志級別設置為 DEBUG 或 TRACE,MyBatis 會輸出非常詳細的日志信息,這會…

鴻蒙:深色模式適配和淺色模式的切換

前言&#xff1a; 有些時候我們需要對應用進行深色模式的適配處理&#xff0c;并且在不需要的時候切換到淺色狀態&#xff0c;下面和大家一起照著官方文檔來學習。 下面是官方文檔的鏈接&#xff1a; https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-dark-…

Coze源碼分析-資源庫-刪除插件-后端源碼-數據訪問和基礎設施層

5. 數據訪問層 5.1 倉儲接口定義 插件倉儲接口 文件位置&#xff1a;backend/domain/plugin/repository/plugin.go type PluginRepository interface {// DeleteDraftPlugin 刪除插件草稿DeleteDraftPlugin(ctx context.Context, pluginID int64) error// DeleteAPPAllPlugins …

案例一: 對基礎選擇器的使用【網頁盒子】

【1】樣例&#xff1a;首先&#xff0c;觀察到&#xff0c;幾個元素豎著排列的&#xff0c;所以使用塊級元素&#xff0c;而不是行內元素。【2】代碼演示<head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,…

爬蟲項目優化:如何用 Redis 實現 “斷點續爬”?避免重復采集電商數據

在電商數據采集場景中&#xff0c;爬蟲常因網絡波動、服務器重啟、IP 封禁等問題中斷。若缺乏斷點續爬機制&#xff0c;重啟后需從頭開始&#xff0c;不僅浪費帶寬與時間&#xff0c;還可能因重復采集導致數據冗余。Redis 憑借其高性能、原子操作、多樣數據結構的特性&#xff…

決策樹概念與原理

決策樹簡介決策樹是一種樹形結構樹中每個內部節點表示一個特征上的判斷&#xff0c;每個分支代表一個判斷結果的輸出&#xff0c;每個葉子節點代表一種分類結果(僅舉例無其他意義或隱喻)就像一個女孩去相親&#xff0c;那么首先詢問是否大于30&#xff0c;大于則不見&#xff0…