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
}

从golang-gin-realworld-example-app项目学写httpapi (二)的更多相关文章

  1. 从golang-gin-realworld-example-app项目学写httpapi (八)

    https://github.com/gothinkster/golang-gin-realworld-example-app/blob/master/common/unit_test.go 单元测试 ...

  2. 从golang-gin-realworld-example-app项目学写httpapi (七)

    https://github.com/gothinkster/golang-gin-realworld-example-app/blob/master/hello.go main调用 package ...

  3. 从golang-gin-realworld-example-app项目学写httpapi (六)

    https://github.com/gothinkster/golang-gin-realworld-example-app/blob/master/users/validators.go 验证器 ...

  4. 从golang-gin-realworld-example-app项目学写httpapi (五)

    https://github.com/gothinkster/golang-gin-realworld-example-app/blob/master/users/middlewares.go 中间件 ...

  5. 从golang-gin-realworld-example-app项目学写httpapi (四)

    https://github.com/gothinkster/golang-gin-realworld-example-app/blob/master/users/routers.go 路由定义 pa ...

  6. 从golang-gin-realworld-example-app项目学写httpapi (三)

    https://github.com/gothinkster/golang-gin-realworld-example-app/blob/master/users/serializers.go 序列化 ...

  7. 从golang-gin-realworld-example-app项目学写httpapi (一)

    https://wangzitian0.github.io/2013/06/29/zero-to-one-1/ https://github.com/gothinkster/golang-gin-re ...

  8. 【饿了么】—— Vue2.0高仿饿了么核心模块&移动端Web App项目爬坑(三)

    前言:接着上一篇项目总结,这一篇是学习过程记录的最后一篇,这里会梳理:评论组件.商家组件.优化.打包.相关资料链接.项目github地址:https://github.com/66Web/ljq_el ...

  9. Golang Gin 项目包依赖管理 godep 使用

    Golang Gin 项目包依赖管理 godep 使用 标签(空格分隔): Go 在按照github.com/tools/godep文档go get完包以后,调整项目结构为$GOPATH/src/$P ...

随机推荐

  1. maven的安装配置超详细教程【含nexus】

    1 下载 下载地址:http://maven.apache.org/download.cgi 界面效果如下: 点击之后进入的apache 软件基金的发布目录,在这里你可以下载apache的所有项目. ...

  2. linux 将一个服务器上的文件或者文件夹复制到另一台服务器上

    使用scp将一个Linux系统中的文件或文件夹复制到另一台Linux服务器上 复制文件或文件夹(目录)命令:  一.复制文件:  (1)将本地文件拷贝到远程  scp 文件名 用户名@计算机IP或者计 ...

  3. InnoDB的B+树索引

    B+树索引其本质就是B+树在数据库中的实现,但是B+索引在数据库中有一个特点就是其高扇出性,因此在数据库中,B+树的高度一般都在2-3层,也就是对于查找某一键值的行记录,最多只需要2到3次IO,这倒不 ...

  4. 认识HDFS分布式文件系统

    1.设计基础目标 (1) 错误是常态,需要使用数据冗余  (2)流式数据访问.数据批量读而不是随机速写,不支持OLTP,hadoop擅长数据分析而不是事物处理.  (3)文件采用一次性写多次读的模型, ...

  5. SQL脚本添加删除修改字段

    1.增加字段     alter table docdsp     add dspcodechar(200)2.删除字段     ALTER TABLE table_NAME DROP COLUMNc ...

  6. [笔记] Python基础---列表

    1.定义列表 列表由数据构成的有限序列,即按照一定的线性顺序排列,排列而成的数据项的集合. 2.创建列表 使用‘[ ]’括起来就已经创建了一个列表,例: my_first_list = [] #空列表 ...

  7. leetcode简单题目两道(5)

    Problem Given an integer (signed bits), write a function to check whether it . Example: Given num = ...

  8. WordNet::Similarity的安装和使用

    简介 WordNet::Similarity是一个Perl实现的软件包,可以用来计算两个概念(或者word sense)之间的语义相似度,它提供了六种计算相似度和三种计算概念之间关联度的方法,所有的这 ...

  9. [Mysql 查询语句]——分组查询group by

    group by (1) group by的含义:将查询结果按照1个或多个字段进行分组,字段值相同的为一组(2) group by可用于单个字段分组,也可用于多个字段分组 select * from ...

  10. springmvc fileupload

    1.pom文件中fileupload的dependencyyinr <dependency> <groupId>commons-fileupload</groupId&g ...