方法 / 步骤

一: 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…