[玩轉GoLang] 5分鐘整合Gin / Gorm框架入門

方法 / 步驟

一: Gin框架

1.1 : 環境 & 項目配置

1, GoLand創建項目

  • 創建main.go
package mainimport ("github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.GET("/", func(c *gin.Context) {c.JSON(200, gin.H{"message": "Hello, Gin!",})})r.Run(":8080") // 啟動服務,監聽 8080 端口
}
  • 創建go.mod文件

2, 初始化Gin項目

go mod tidy
go get -u github.com/gin-gonic/gin
# 或者在go.mod 文件中添加下面依賴
require github.com/gin-gonic/gin v1.9.0

3, 編譯配置

# 更改輸出目錄為 xxxx/target# 工具實參 去除編譯相關
-ldflags="-s -w"

在這里插入圖片描述

1.2 路由 & 出入參

// 基本路由
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {c.JSON(200, gin.H{"message": "pong"})
})// 路由分組 (getUsers)
api := r.Group("/api")
{api.GET("/users", getUsers)api.POST("/users", createUser)
}r.Run(":8080")// 綁定入參
type User struct {Name string `json:"name"`Age  int    `json:"age"`
}r.POST("/user", func(c *gin.Context){var u Userif err := c.ShouldBindJSON(&u); err != nil {c.JSON(400, gin.H{"error": err.Error()})return}c.JSON(200, gin.H{"status": "ok", "user": u})
})
// 獲取 URL 參數
r.GET("/user/:id", func(c *gin.Context){id := c.Param("id")c.JSON(200, gin.H{"id": id})
})

Gin Context

Gin 的 Context 特性(相比 Java 更輕量)

  • Gin 的 Context 集成了請求、響應、JSON、參數、Header 等
  • 無需額外注入 HttpServletRequest / Response
r.GET("/info", func(c *gin.Context){path := c.Request.URL.Pathheader := c.GetHeader("User-Agent")c.JSON(200, gin.H{"path": path, "ua": header})
})

1.3 Gin + Go 并發入門(相比 Java 線程更輕量)

  • Go 原生 goroutine + Gin Context 可以輕松實現并發處理
  • 對比 Java 線程,goroutine 占用資源極少
r.GET("/async", func(c *gin.Context){// 創建協程functiongo func(ctx *gin.Context){time.Sleep(2 * time.Second)fmt.Println("Async processing done")}(c.Copy()) // 必須使用 Copy() 避免 Context 并發問題c.JSON(200, gin.H{"status": "processing"})
})

通過上面可以看出我們的端口號都是在代碼里面寫死的8080, 實際在生產中這么寫死很不優雅的,所以下面就用另外一種優雅的方式來實現:

1.4 環境變量管理:godotenv

  • go.mod文件中 添加相關依賴
require (github.com/gin-gonic/gin v1.10.1// godotenv環境變量依賴github.com/joho/godotenv v1.5.1
)
  • .env 文件內容
KEY=value
DB_USER=root
DB_PASS=123456
PORT=9999
  • 更改main.go中的 端口號使用配置里面進行加載
package mainimport ("fmt""github.com/gin-gonic/gin""github.com/joho/godotenv""log""os""time"
)type Users struct {Name string `json:"name"`Age  int    `json:"age"`
}func main() {// 1. 使用godotenv加載 .env 文件 (如果不配置gin的默認端口號是8080)err := godotenv.Load()if err != nil {log.Println("No .env file found, using system environment variables")}r := gin.Default()port := os.Getenv("PORT")r.Run(":" + port)r.GET("/", func(c *gin.Context) {c.JSON(200, gin.H{"message": "Hello, Gin!",})})api := r.Group("/api"){api.GET("/users", getUsers)api.POST("/users", createUser)}// Gin 并發處理入門r.GET("/async", func(c *gin.Context) {go func(ctx *gin.Context) {time.Sleep(2 * time.Second)fmt.Println("Async processing done")}(c.Copy()) // 必須使用 Copy() 避免 Context 并發問題c.JSON(200, gin.H{"status": "processing"})})// 啟動服務,監聽 8080 端口//r.Run(":8080")
}// 該function沒有返回值,gin框架返回的json使用context進行包裝返回
func createUser(context *gin.Context) {fmt.Println("this is createUser")newUser := Users{Name: "alice", Age: 12}//todo 進行創建用戶的業務處理context.JSON(200, gin.H{"success": true, "data": newUser})
}func getUsers(context *gin.Context) {newUser := Users{Name: "alice", Age: 12}context.JSON(200, gin.H{"success": true, "data": newUser})fmt.Println("this is getUsers")
}

二: GORM框架集成

GORM介紹

?	GitHub: https://github.com/go-gorm/gorm
?	特點:
?	功能全:CRUD、事務、關聯、鉤子、分頁、軟刪除
?	鏈式 API,支持自定義 SQL
?	支持 MySQL、PostgreSQL、SQLite、SQL Server 等
?	適用場景: 企業級項目、快速開發、需要自動 CRUD
?	用戶量: GitHub Star ~33k+,社區活躍,文檔豐富

相對于其他ORM框架
在這里插入圖片描述

1?? 前置條件 & 項目結構設計

?	已安裝 Go(推薦 Go 1.20+)
?	已安裝 MySQL 或 SQLite(方便本地測試)
?	已安裝 GoLand 或 VSCode(任選)
gin-gorm-demo/
├── main.go                # 程序入口
├── config/                # 配置文件
│   └── config.go
├── model/                 # 數據模型(類似 entity)
│   └── user.go
├── dao/                   # 數據訪問層(類似 mapper/repository)
│   └── user_dao.go
├── service/               # 業務邏輯層
│   └── user_service.go
├── router/                # 路由配置
│   └── router.go
├── handler/               # 控制器層(類似 controller)
│   └── user_handler.go
├── .env                   # 環境配置
└── go.mod

在這里插入圖片描述

  • 初始化項目
# 新建目錄
mkdir gin-gorm-demo && cd gin-gorm-demo# 初始化 Go 模塊
go mod init gin-gorm-demo# 安裝依賴
go get -u github.com/gin-gonic/gin
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql# 可選:本地快速調試
go get -u gorm.io/driver/sqlite   
  • MySQL 初始化SQL
-- 初始化表
CREATE TABLE `users`
(`id`    BIGINT UNSIGNED AUTO_INCREMENT,`name`  VARCHAR(100),`email` VARCHAR(255),PRIMARY KEY (`id`),UNIQUE INDEX `idx_users_email` (`email`)
);

2?? .env 文件

(用于本地調試和生產環境切換,借助 godotenv 讀取)

APP_PORT=8080
DB_DRIVER=mysql
DB_DSN=root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local

3?? config/config.go

package configimport ("log""os""github.com/joho/godotenv"
)type Config struct {AppPort stringDBDriver stringDBDsn    string
}var Cfg Configfunc InitConfig() {_ = godotenv.Load() // 讀取 .env 文件Cfg = Config{AppPort: getEnv("APP_PORT", "8080"),DBDriver: getEnv("DB_DRIVER", "sqlite"),DBDsn:    getEnv("DB_DSN", "test.db"),}
}func getEnv(key, defaultVal string) string {if value, exists := os.LookupEnv(key); exists {return value}return defaultVal
}

4?? model/user.go

package modeltype User struct {ID    uint   `gorm:"primaryKey"`Name  string `gorm:"size:100"`Email string `gorm:"uniqueIndex"`
}

5?? dao/user_dao.go

package daoimport ("gin-gorm-demo/model""gorm.io/gorm"
)type UserDao struct {DB *gorm.DB
}func NewUserDao(db *gorm.DB) *UserDao {return &UserDao{DB: db}
}func (d *UserDao) Create(user *model.User) error {return d.DB.Create(user).Error
}func (d *UserDao) FindAll() ([]model.User, error) {var users []model.Usererr := d.DB.Find(&users).Errorreturn users, err
}func (d *UserDao) FindByID(id string) (*model.User, error) {var user model.Usererr := d.DB.First(&user, id).Errorreturn &user, err
}

6?? service/user_service.go

package serviceimport ("gin-gorm-demo/dao""gin-gorm-demo/model"
)type UserService struct {UserDao *dao.UserDao
}func NewUserService(userDao *dao.UserDao) *UserService {return &UserService{UserDao: userDao}
}func (s *UserService) CreateUser(user *model.User) error {return s.UserDao.Create(user)
}func (s *UserService) GetUsers() ([]model.User, error) {return s.UserDao.FindAll()
}func (s *UserService) GetUserByID(id string) (*model.User, error) {return s.UserDao.FindByID(id)
}

7?? handler/user_handler.go

package handlerimport ("gin-gorm-demo/model""gin-gorm-demo/service""net/http""github.com/gin-gonic/gin"
)type UserHandler struct {UserService *service.UserService
}func NewUserHandler(userService *service.UserService) *UserHandler {return &UserHandler{UserService: userService}
}func (h *UserHandler) CreateUser(c *gin.Context) {var user model.Userif err := c.ShouldBindJSON(&user); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}if err := h.UserService.CreateUser(&user); err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "保存失敗"})return}c.JSON(http.StatusOK, user)
}func (h *UserHandler) GetUsers(c *gin.Context) {users, err := h.UserService.GetUsers()if err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "查詢失敗"})return}c.JSON(http.StatusOK, users)
}func (h *UserHandler) GetUserByID(c *gin.Context) {id := c.Param("id")user, err := h.UserService.GetUserByID(id)if err != nil {c.JSON(http.StatusNotFound, gin.H{"error": "用戶不存在"})return}c.JSON(http.StatusOK, user)
}

8?? router/router.go

package routerimport ("gin-gorm-demo/handler""github.com/gin-gonic/gin"
)func SetupRouter(userHandler *handler.UserHandler) *gin.Engine {r := gin.Default()r.POST("/users", userHandler.CreateUser)r.GET("/users", userHandler.GetUsers)r.GET("/users/:id", userHandler.GetUserByID)return r
}

9?? main.go

package mainimport ("fmt""gin-gorm-demo/config""gin-gorm-demo/dao""gin-gorm-demo/handler""gin-gorm-demo/model""gin-gorm-demo/router""gin-gorm-demo/service""log""gorm.io/driver/mysql""gorm.io/driver/sqlite""gorm.io/gorm"
)func initDB() *gorm.DB {var db *gorm.DBvar err errorif config.Cfg.DBDriver == "mysql" {db, err = gorm.Open(mysql.Open(config.Cfg.DBDsn), &gorm.Config{})} else {db, err = gorm.Open(sqlite.Open(config.Cfg.DBDsn), &gorm.Config{})}if err != nil {log.Fatal("數據庫連接失敗:", err)}// 自動建表db.AutoMigrate(&model.User{})return db
}func main() {// 初始化配置config.InitConfig()// 初始化數據庫db := initDB()// 初始化分層對象userDao := dao.NewUserDao(db)userService := service.NewUserService(userDao)userHandler := handler.NewUserHandler(userService)// 路由r := router.SetupRouter(userHandler)// 啟動服務addr := fmt.Sprintf(":%s", config.Cfg.AppPort)r.Run(addr)
}

打包運行

在這里插入圖片描述

相關源碼鏈接

  • GoLang整合 gin + gorm 框架源碼
    https://download.csdn.net/download/YangCheney/91873119

📚 參考資料 & 致謝

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

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

相關文章

【項目復現】MOOSE-Chem 用于重新發現未見化學科學假說的大型語言模型

項目地址 ZonglinY/MOOSE-Chem: [ICLR 2025] --- ZonglinY/MOOSE-Chem: [ICLR 2025] https://github.com/ZonglinY/MOOSE-Chem git代碼同步&#xff1a; 同步地址如下&#xff1a;QianPengfei1/MOOSE-Chem: [ICLR 2025] <MOOSE-Chem: Large Language Models for Rediscove…

深入解析TCP核心機制:連接管理、流量與擁塞控制

目錄 一、三次握手與四次揮手&#xff1a;可靠連接的建立與終止 1. 三次握手 - 建立連接 為什么是三次&#xff1f; 2. 四次揮手 - 終止連接 為什么需要TIME_WAIT狀態&#xff1f; 二、流量控制與滑動窗口&#xff1a;解決收發速度不匹配 核心機制&#xff1a;滑動窗口協…

如何在 DevOps 管道中實現 AI?

對于許多尋求提升效率、優化性能并縮短上市時間的組織而言,將人工智能 (AI) 集成到 DevOps 流水線中已成為一項戰略舉措。AI 與 DevOps 的結合,有時被稱為 AIOps(面向 IT 運營的人工智能),正在重塑開發和運營團隊構建、測試、發布和維護軟件應用程序的方式。本文將引導您了…

【Agent】DeerFlow Planner:執行流程與架構設計(基于真實 Trace 深度解析)

本文檔系統闡述 DeerFlow 中 Planner 的職責邊界、端到端執行流程、關鍵節點設計、數據結構、容錯與人審機制&#xff0c;以及與研究/編碼子代理的協同方式。面向開發與運維讀者&#xff0c;幫助快速理解與調優 Planner 相關鏈路。 時序圖&#xff08;Sequence Diagram&#xf…

后端接口防止XSS漏洞攻擊

有這樣一個場景&#xff0c;首先構建一個docx文件并插入超鏈接&#xff08;惡意的鏈接&#xff09;&#xff0c;上傳到文件服務器后獲取對應的文件filekey。現在我們提供一個預覽接口&#xff0c;通過filekey便可以預覽&#xff0c;在根據filekey轉html文檔返回給頁面的時候由于…

4.1Vue基本使用

1.使用Vue-引入 Vue 的本質,就是一個 JavaScript 的庫: 剛開始我們不需要把它想象的非常復雜; 我們就把它理解成一個已經幫我們封裝好的庫; 在項目中可以引入并且使用它即可。 那么安裝和使用 Vue 這個 JavaScript 庫有哪些方式呢? 方式一:在頁面中通過 CDN 的方式來引…

CAD繪圖:雜項

一、樣式標注管理器 新建CAD圖紙的樣式標注是定死的,需要手動去改變合適的大小 1)命令行中直接輸入“D”,打開樣式標注管理器 2)點擊“修改”,可以改變其顏色,線條樣式以及文字大小、顏色、字體等 3)若想添加字體: a)在網上下載需要的字體 b)右鍵Auto CAD圖標(…

Git上有更新而本地無更新時的解決方案

問題分析 分支名稱不匹配&#xff1a;你嘗試推送到 main 分支&#xff0c;但你當前在 master 分支上遠程倉庫有新內容&#xff1a;遠程倉庫包含你本地沒有的提交&#xff0c;需要先拉取 解決方案 方法1&#xff1a;繼續使用 master 分支 # 1. 先拉取遠程更改 git pull origin m…

用于骨盆骨折復位與固定自動術前手術規劃的基于幾何的端到端流水線|文獻速遞-最新醫學人工智能文獻

Title題目An End-to-End Geometry-Based Pipeline forAutomatic Preoperative Surgical Planning ofPelvic Fracture Reduction and Fixation用于骨盆骨折復位與固定自動術前手術規劃的基于幾何的端到端流水線01文獻速遞介紹骨盆骨折及其術前規劃相關研究背景與本文方法 骨盆骨…

【導航】OS復習

【OS】操作系統概述-CSDN博客 【OS】PV-CSDN博客 【OS】進程與線程-CSDN博客 【OS】文件管理-CSDN博客 【OS】IO_檢查用戶io請求的合法性-CSDN博客

Google Nano-banana AI模型圖像生成能力實證分析:基于47個案例的系統化技術驗證

Google Nano-banana AI模型官方示例庫&#xff08;Awesome-Nano-Banana&#x1f34c;-images&#xff09;&#xff0c;通過系統化分析47個技術案例&#xff0c;實證驗證其在圖像生成、編輯與轉換任務中的核心能力。所有測試基于Apache 2.0開源許可的公開案例數據集&#xff0c;…

MySQL 多表操作與復雜查詢:深入理解多表關系和高級查詢

大家好&#xff01;今天我們要深入探討 MySQL 中兩個非常重要的主題——多表操作 和 復雜查詢。一. 多表操作什么是多表操作&#xff1f;在實際應用中&#xff0c;數據通常分布在多個表中&#xff0c;需要通過多表操作來獲取完整信息。比如&#xff0c;一個學生表和一個課程表之…

Java入門級教程7——eclipse新建Maven項目,創建和連接數據庫,創建數據庫表

目錄 1.若沒有Maven項目&#xff0c;可以選擇新建 2.添加Maven依賴 3.數據庫的創建 3.1 新建連接 --> 創建數據庫 3.2 創建數據庫表 4.連接數據庫 1.若沒有Maven項目&#xff0c;可以選擇新建 步驟一&#xff1a;點擊 File --> New --> Project 步驟二&#xf…

請求庫-axios

Axios 是一個基于 Promise 的 HTTP 客戶端庫&#xff0c;用于瀏覽器和 Node.js 環境。它支持發送異步 HTTP 請求&#xff0c;并提供了簡潔的 API 來處理請求和響應。1、安裝axios因為axios是一個第三方庫&#xff0c;所以在使用之前我們需要先安裝第三方模塊。安裝 Axios 需通過…

電子煙的4種屏幕驅動集成語音方案介紹

目前電子煙在全球市場的表現非常不錯&#xff0c;很多國產電子煙廠家都有非常不錯的產品&#xff0c;而屏幕驅動方案是電子煙智能化的重要組成部分&#xff0c;今天就給大家帶來電子煙的4種主流屏幕驅動方案(含2025年最新版方案)。?  方案一、LED顯示方案語音播報集成方案 W…

無法加載 DLL“xxxxxxx.dll”: 找不到指定的模塊。 (異常來自 HRESULT:0x8007007E)。

(無法加載 DLL“xxxxxxx.dll”: 找不到指定的模塊。 (異常來自 HRESULT:0x8007007E)。) 這個錯誤&#xff1a; 無法加載 DLL“ZH_P2P_Libx64.dll”: 找不到指定的模塊。 (異常來自 HRESULT:0x8007007E) 意味著你的程序在運行時試圖加載一個名為 xxxxxxx.dll 的動態鏈接庫&#…

Flask/Django 生產部署:Gunicorn vs Nginx,Windows 與 Linux 實戰指引

Flask/Django 生產部署&#xff1a;Gunicorn vs Nginx&#xff0c;Windows 與 Linux 實戰指引 TL;DR Gunicorn&#xff1a;Python WSGI 應用服務器&#xff0c;運行 Flask/Django&#xff08;Linux 用&#xff09;。Nginx&#xff1a;反向代理/網關&#xff08;TLS、靜態、限流…

Nginx 優化與防盜鏈全解析:從性能調優到資源保護

Nginx 優化與防盜鏈全解析&#xff1a;從性能調優到資源保護 文章目錄Nginx 優化與防盜鏈全解析&#xff1a;從性能調優到資源保護一、基礎安全優化&#xff1a;隱藏版本號1.1 查看當前版本號1.2 兩種隱藏/修改方案方案一&#xff1a;修改配置文件&#xff08;快速隱藏&#xf…

HOT100--Day20--39. 組合總和,22. 括號生成,79. 單詞搜索

HOT100–Day20–39. 組合總和&#xff0c;22. 括號生成&#xff0c;79. 單詞搜索 每日刷題系列。今天的題目是《力扣HOT100》題單。 題目類型&#xff1a;回溯。 關鍵&#xff1a;掌握排列&#xff0c;組合。記得回溯。可以重復選的話&#xff0c;下一層index從哪里開始&#x…

高并發場景下的“命令執行”注入繞道記

環境&#xff1a;CentOS 8 OpenResty 1.21 PHP-FPM 8.0 背景&#xff1a;營銷團隊上線了一個“圖片裁剪”接口&#xff0c;參數直接拼進 shell_exec&#xff0c;結果被打成“礦機”。1. 發現&#xff1a;流量突增 30 倍&#xff0c;卻不見數據庫慢查詢 iftop -i eth0出站 1.8…