• 从golang-gin-realworld-example-app项目学写httpapi (二)


    https://github.com/gothinkster/golang-gin-realworld-example-app/blob/master/users/models.go

    模型定义

    users/models.go

    package users
    
    import (
    	"errors"
    	"github.com/jinzhu/gorm"
    	"github.com/wangzitian0/golang-gin-starter-kit/common"
    	"golang.org/x/crypto/bcrypt"
    )
    
    // UserModel对象,对应用户表
    // gorm结构体标记,常用的column, type, size, primary_key, unique, index, unique_index, not null, -(忽略此字段)
    type UserModel struct {
    	ID           uint    `gorm:"primary_key"`
    	Username     string  `gorm:"column:username"`
    	Email        string  `gorm:"column:email;unique_index"`
    	Bio          string  `gorm:"column:bio;size:1024"`
    	Image        *string `gorm:"column:image"`
    	PasswordHash string  `gorm:"column:password;not null"`
    }
    
    // FollowModel对象,对应关注表
    // gorm.Model 是一个包含了基本字段的结构(struct), 其中包括字段: ID、CreatedAt、UpdatedAt、DeletedAt(逻辑删除字段)
    type FollowModel struct {
    	gorm.Model
    	Following    UserModel
    	FollowingID  uint
    	FollowedBy   UserModel
    	FollowedByID uint
    }
    
    // 函数 用于创建表结构
    // 如果不特别指定表名,以对象名大写单词拆分,用下划线连接,未尾加s 指定表名,如UserModel -> user_models
    func AutoMigrate() {
        // 获取数据库连接
    	db := common.GetDB()
    
        // 整合表结构,会创建新增的字段,不会改变原有字段内容,可以选择db.CreateTable代替
    	db.AutoMigrate(&UserModel{})
    	db.AutoMigrate(&FollowModel{})
    	//db.CreateTable(&UserModel{})
    	//db.CreateTable(&FollowModel{})
    }
    
    // UserModel对象的内置方法 用于设置密码, 使用 if err := user.setPassword("password0"); err !=nil { ... }
    func (u *UserModel) setPassword(password string) error {
    	if len(password) == 0 {
    		return errors.New("password should not be empty!")
    	}
    
    	bytePassword := []byte(password)
    	
        // `bcrypt generator cost` 取值 [4, 32] 间
    	passwordHash, _ := bcrypt.GenerateFromPassword(bytePassword, bcrypt.DefaultCost)
    	u.PasswordHash = string(passwordHash)
    	return nil
    }
    
    // UserModel对象的内置方法 用于校验密码,使用 if err := user.checkPassword("password0"); err != nil { ... }
    func (u *UserModel) checkPassword(password string) error {
    	bytePassword := []byte(password)
    	byteHashedPassword := []byte(u.PasswordHash)
            
        return bcrypt.CompareHashAndPassword(byteHashedPassword, bytePassword)
    }
    
    // UserModel对象相关的函数 用于查找符合条件的第一条记录,使用 user, err := FindOneUser(&UserModel{Username: "username0"})
    func FindOneUser(condition interface{}) (UserModel, error) {
    	db := common.GetDB()
    	var model UserModel
        // condition使用Struct 或者 Map
    	err := db.Where(condition).First(&model).Error
    	return model, err
    }
    
    // UserModel对象相关的函数 用于插入记录,使用 if err := SaveOne(&userModel); err != nil { ... }
    func SaveOne(data interface{}) error {
    	db := common.GetDB()
    	err := db.Save(data).Error
    	//err := db.Create(data).Error
    	return err
    }
    
    // UserModel对象的内置方法 用于更新记录,使用 if err := user.Update(UserModel{Username: "wangzitian0"}); err !=nil { ... }
    func (model *UserModel) Update(data interface{}) error {
    	db := common.GetDB()
    	err := db.Model(model).Update(data).Error
    	return err
    }
    
    // UserModel对象的内置方法 建立用户间关注(user1 -> user2),使用 if err := user1.following(user2); err != nil { ... }
    func (u UserModel) following(v UserModel) error {
    	db := common.GetDB()
    
    	var follow FollowModel
        // 查询是否建立关注,如果没有则建立
    	err := db.FirstOrCreate(&follow, &FollowModel{
    		FollowingID:  v.ID,
    		FollowedByID: u.ID,
    	}).Error
    	
        return err
    }
    
    // UserModel对象的内置方法 查询用户间是否关注(user1 -> user2),使用 if  ok := user1.isFollowing(user2); if ok { ... }
    func (u UserModel) isFollowing(v UserModel) bool {
    	db := common.GetDB()
    
    	var follow FollowModel
    	db.Where(FollowModel{
    		FollowingID:  v.ID,
    		FollowedByID: u.ID,
    	}).First(&follow)
    
        // 查询是否关注,如果有关注,返回True(用户ID非0值),没有关注(用户ID为0值)
    	return follow.ID != 0
    }
    
    // UserModel对象的内置方法 取消用户间关注,使用 if err := user1.unFollowing(user2); err != nil { ... }
    func (u UserModel) unFollowing(v UserModel) error {
    	db := common.GetDB()
    
    	err := db.Where(FollowModel{
    		FollowingID:  v.ID,
    		FollowedByID: u.ID,
    	}).Delete(FollowModel{}).Error
    	
        //因为FollowModel包含DeletedAt字段,此处为逻辑删除,实际执行的是 UPDATE follow_models SET deleted_at="2013-10-29 10:23" WHERE ...;
        return err
    }
    
    // UserModel对象的内置方法 查询指定用户的所有关注,使用 followings := user1.GetFollowings()
    func (u UserModel) GetFollowings() []UserModel {
    	db := common.GetDB()
    
        // 事务处理开始
    	tx := db.Begin()
    	var follows []FollowModel
    	var followings []UserModel
    
        // 获取关注表里所有相关的关联记录
    	tx.Where(FollowModel{
    		FollowedByID: u.ID,
    	}).Find(&follows)
    
        // 循环每条关联记录	
        for _, follow := range follows {
    		var userModel UserModel
            // 第2参数Following为外键名
    		tx.Model(&follow).Related(&userModel, "Following")
    		followings = append(followings, userModel)
    	}
    
        // 事务处理结束	
        tx.Commit()
    	return followings
    }
    
  • 相关阅读:
    Ubuntu 安装第三方工具
    mysql 安装
    启动springboot的项目的时候报错 Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
    idea激活码 2020年12月17日 可以用到 2021年2月10号
    logback-spring.xml相关配置的注释
    Exception in thread "main" java.lang.UnsupportedOperationException 数组转化为list后,返回的List是具有固定长度的私有静态内部类
    一.设计模式之六大原则
    redis经典面试题
    windows远程连接linux服务器的redis 连接不上
    linux下安装mysql 8.* MySQL连接时找不到mysql.sock文件
  • 原文地址:https://www.cnblogs.com/liujitao79/p/9967655.html
Copyright © 2020-2023  润新知