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更多用法
更多的用法参考中文官网