当前位置: 首页 > news >正文

Go从入门到精通(23) - 一个简单web项目-使用数据库存储数据

Go从入门到精通(23)

一个简单web项目-使用数据库存储数据


文章目录

  • Go从入门到精通(23)
  • 前言
  • 安装依赖
  • 创建数据库模型
  • 配置数据库连接
  • 修改用户处理函数使用数据库
  • 修改主函数初始化数据库
  • 添加辅助函数
  • 配置环境变量
  • 插件与扩展
  • 小结
  • gorm更多用法


前言

GORM 是 Go 语言中最流行的 ORM(对象关系映射)库之一,用于简化数据库操作。它提供了直观的 API,支持主流数据库(如 MySQL、PostgreSQL、SQLite 等),并具备自动迁移、关联查询、事务管理等功能。


安装依赖

go get -u gorm.io/gorm
go get -u gorm.io/driver/postgres

创建数据库模型

// app/repository/models/user.go
package modelsimport ("time"
)// User 用户模型
type User struct {ID        string    `gorm:"primaryKey;size:36" json:"id"`Username  string    `gorm:"unique;not null;size:50" json:"username"`Password  string    `gorm:"not null" json:"-"` // 不返回密码Email     string    `gorm:"unique;not null;size:100" json:"email"`CreatedAt time.Time `json:"created_at"`UpdatedAt time.Time `json:"updated_at"`
}

配置数据库连接

数据库安装与使用自行查阅其他资料,这里不再讲解

package repositoryimport ("go-web-demo/app/repository/models""gorm.io/driver/mysql""gorm.io/driver/postgres""gorm.io/gorm""log""os"
)var DB *gorm.DBfunc InitGormDB() error {dsn := os.Getenv("DATABASE_DSN")if dsn == "" {// 默认使用 PostgreSQLdsn = "host=localhost user=postgres password=password dbname=user_db port=5432 sslmode=disable TimeZone=Asia/Shanghai"}var err errorvar dialect gorm.Dialector// 根据环境变量选择数据库驱动dbDriver := os.Getenv("DB_DRIVER")switch dbDriver {case "mysql":dialect = mysql.Open(dsn)default:dialect = postgres.Open(dsn)}DB, err = gorm.Open(dialect, &gorm.Config{})if err != nil {log.Fatalf("无法连接数据库: %v", err)return err}// 自动迁移模型if err := DB.AutoMigrate(&models.User{}); err != nil {log.Fatalf("数据库迁移失败: %v", err)return err}log.Println("数据库连接成功")return nil
}

修改用户处理函数使用数据库

// handlers/user_handlers.go
package handlersimport ("encoding/json""net/http""strings""golang.org/x/crypto/bcrypt""gorm.io/gorm""your-project/database""your-project/models"
)// 全局变量替换为数据库连接
// var users = make(map[string]models.User)
// var nextUserID = 1// RegisterHandler 注册新用户
func RegisterHandler(c *gin.Context) {var request dto.RegisterRequest// 绑定并验证请求if err := c.ShouldBindJSON(&request); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}// 检查用户名是否已存在var existingUser models.Userif err := repository.DB.Where("username = ?", request.Username).First(&existingUser).Error; err == nil {c.JSON(http.StatusConflict, gin.H{"error": "用户名已存在"})return} else if !errors.Is(err, gorm.ErrRecordNotFound) {c.JSON(http.StatusInternalServerError, gin.H{"error": "数据库错误"})return}// 哈希密码hashedPassword, err := bcrypt.GenerateFromPassword([]byte(request.Password), bcrypt.DefaultCost)if err != nil {logger.Sugar.Errorw("密码哈希失败", "error", err)c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to hash password"})return}// 创建新用户user := models.User{ID:        utils.GenerateUniqueID(), // 实现一个生成唯一ID的函数Username:  request.Username,Password:  string(hashedPassword),Email:     request.Email,CreatedAt: time.Now(),UpdatedAt: time.Now(),}// 保存到数据库if err := repository.DB.Create(&user).Error; err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "创建用户失败"})return}// 生成令牌token, err := utils.GenerateToken(user.ID)if err != nil {logger.Sugar.Errorw("生成令牌失败", "error", err)c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"})return}c.JSON(http.StatusCreated, dto.TokenResponse{Token: token})
}// 其他处理函数类似修改...

修改主函数初始化数据库

// main.go
func main() {// 连接数据库if err := repository.InitGormDB(); err != nil {panic(err)}//.. 其他逻辑
}

添加辅助函数

// utils/utils.go
package utilsimport ("crypto/rand""encoding/hex""time""github.com/dgrijalva/jwt-go"
)// 生成唯一ID
func GenerateUniqueID() string {b := make([]byte, 16)rand.Read(b)return hex.EncodeToString(b)
}// 生成JWT令牌
func GenerateToken(userID string) (string, error) {token := jwt.New(jwt.SigningMethodHS256)claims := token.Claims.(jwt.MapClaims)claims["id"] = userIDclaims["exp"] = time.Now().Add(time.Hour * 24).Unix()return token.SignedString([]byte("your-secret-key"))
}

配置环境变量

根据自己环境配置,下面为例子

DATABASE_DSN=host=localhost user=postgres password=password dbname=user_db port=5432 sslmode=disable

插件与扩展

GORM 支持通过插件增强功能,例如:

  • gorm.io/plugin/dbresolver:读写分离、多数据库支持
  • gorm.io/plugin/soft_delete:软删除(逻辑删除)
  • gorm.io/plugin/optimisticlock:乐观锁实现

小结

上面的例子只是简单的说明gorm的用法,实际项目中使用可能会更加复杂,中大型项目可能会要求,数据库交互层(repository)独立,外部通过接口来调用,大家可自行实践。

gorm更多用法

更多的用法参考中文官网

http://www.dtcms.com/a/278821.html

相关文章:

  • 解决chrome v2 版本插件不支持
  • 上下文管理器 和 contextlib 模块
  • [硬件电路-22]: 为什么模拟电路信号处理运算的精度不如数字信号处理运算?
  • 《Llava:Visual Instruction Tuning》论文精读笔记
  • 基于Chinese-CLIP与ChromaDB的中文图像检索功能实现
  • 人工智能如何重构能源系统以应对气候变化?
  • 动态规划题解——单词拆分【LeetCode】
  • openEuler系统PCIE降速方法简介
  • 【2025/07/14】GitHub 今日热门项目
  • Self - RAG工作步骤
  • 【HTML】五子棋(精美版)
  • 【Java EE】多线程-初阶 认识线程(Thread)
  • 【C语言进阶】指针面试题详解(2)
  • 面试 | JS 面试题 整理(更ing)2/34
  • Android 16系统源码_窗口动画(二)窗口显示动画源码调用流程
  • 护照阅读器:国外证件识别的 OCR “解码师”
  • Python 中调用阿里云 OCR(Optical Character Recognition,光学字符识别)服务
  • STM32介绍和GPIO
  • stm32-Modbus主机移植程序理解以及实战
  • argus/nvarguscamerasrc 远程显示报错
  • 项目一第一天
  • 纯数学专业VS应用数学专业:这两个哪个就业面更广?
  • C++后端面试八股文
  • Linux 基础命令详解:从入门到实践(1)
  • JAVA 并发 ThreadLocal
  • RestAssured(Java)使用详解
  • 19.数据增强技术
  • 管程! 解决互斥,同步问题的现代化手段(操作系统os)
  • Java行为型模式---模板方法模式
  • Imx6ull用网线与电脑连接