共计 3791 个字符,预计需要花费 10 分钟才能阅读完成。
背景
去年缓缓开始接触了 Go 语言,也在公司写了几个 Go 的生产我的项目。我是从 Java 转过来的。(其实也不算转,公司用啥,我用啥)在这个过程中,老是想用 Java 的思维写 Go,在开始的一两个月,那是边写边吐槽。
俊俏的错误处理,没有流式解决,还居然没有泛型,框架生态链不成熟,没有一家独大的相似 Spring 的框架。(其实当初写了快一年的 Go,Go 还是挺香的,哈哈)
明天,我来聊一下,我在我在写 Go 过程中用的最多 orm 框架 gorm。
Java 的 orm
写过 Java 的根本都晓得 Mybatis,Mybatis-plus。
在 Mybatis-plus 中操作单表十分不便,通过 QueryWrapper,对于单表的操作十分的丝滑,没有任何的思维累赘。
相似上面这样:
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(User::getUsername,"zhangsan").eq(User::getAge,18);
userMapper.selectList(queryWrapper);
复制代码
Go 的 orm
这里的条件查问都须要开发手动来拼接字符串,如果我的项目比拟大的话,就会看到漫天飞的 SQL 字段,保护起来十分麻烦。
var users []*User
sqlResult := db.Where(“username = ? and age = ?”, “zhangsan”, 18).Find(&users)
复制代码
解决形式
写了一段时间的 Go 之后,切实不想每次都写这些字符串拼接了,于是我给 gorm 封装了一个 gorm-plus。
这里我应用到了 go 1.18 的泛型。泛型出了这么久,也该应用上了。
其实就是把 Mybatis-plus 的那套语法借鉴了一下。(好吧,就是抄他的)
Mybatis-plus 对于单表操作提供了十分多的 CRUD 操作。
我给 gorm-plus 也提供了相似的操作
上面是具体用法
下载:
go get github.com/acmestack/gorm-plus
复制代码
初始化 sql
DROP TABLE IF EXISTS users
;
CREATE TABLE users
(
`id` int(0) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`age` int(0) NULL DEFAULT NULL,
`phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`score` int(0) NULL DEFAULT NULL,
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`dept` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`created_at` datetime(0) NULL DEFAULT NULL,
`updated_at` datetime(0) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
复制代码
连贯数据库
var GormDb *gorm.DB
func init() {
dsn := “root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local”
var err error
GormDb, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
log.Fatalln(err)
}
gplus.Init(GormDb)
}
复制代码
插入语句
user := &User{Username: “zhangsan”, Password: “123456”, Age: 18, Score: 100, Dept: “A 部门 ”}
result := gplus.Insert(user)
fmt.Println(result.RowsAffected)
复制代码
查问语句
依据 id 查问:
留神这里须要传入泛型 User
user, resultDb := gplus.SelectByIdUser
fmt.Println(user, resultDb.RowsAffected)
复制代码
依据 ids 查问:
var ids = []int{1,2}
users, resultDb := gplus.SelectByIdsUser
fmt.Println(users, resultDb.RowsAffected)
复制代码
条件查问:
q := gplus.NewQuery[User]()
q.Eq(“username”, “zhangsan”).Eq(“age”,18)
users, resultDb := gplus.SelectList(q)
fmt.Println(users,resultDb.RowsAffected)
复制代码
比照一下 Mybatis-plus 写法基本一致了。
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(User::getUsername,"zhangsan").eq(User::getAge,18);
userMapper.selectList(queryWrapper);
复制代码
更多操作请查看:
github.com/acmestack/g…
gplus 工具
其实下面的写法还是须要写数据库的字段名,如果数据库的字段名很多,咱们很容易写错,导致不必要的 bug 产生。
一旦名称长,非常容易误写,而且如果有字段名称批改的话,还须要全局搜寻一个个地批改,比拟麻烦。
Go 没有提供相似 Java 的 lambad 表达式或者 C# 中 nameof 形式间接获取某个对象的字段名称的操作,然而咱们能够通过生成代码的形式生成字段名。
所有就有了 gplus,它作用就是自动识别构造体,把构造体的字段名生成进去。
下载应用:
go install github.com/acmestack/gorm-plus/cmd/gplus@latest
复制代码
通过 gplus gen paths= 门路,gplus 会自动识别带有 // +gplus:column=true 正文的构造体,给这个构造体生成字段。
gplus 会在输出的门路上面生成 zz_gen.column.go 文件。
例如:
在 example 目录下创立了了一个 users.go 目录,执行 gplus gen paths=./eample
users.go
// +gplus:column=true
type User struct {
ID int64
Username string gorm:"column:username"
Password string
Address string
Age int
Phone string
Score int
Dept string
CreatedAt time.Time
UpdatedAt time.Time
}
复制代码
zz_gen.column.go(主动生成的)
var UserColumn = struct {
ID string
Username string
Password string
Address string
Age string
Phone string
Score string
Dept string
CreatedAt string
UpdatedAt string
}{
ID: “id”,
Username: “username”,
Password: “password”,
Address: “address”,
Age: “age”,
Phone: “phone”,
Score: “score”,
Dept: “dept”,
CreatedAt: “created_at”,
UpdatedAt: “updated_at”,
}
复制代码
其实你本人也能够手写这个文件,只不过通过工具生成更加不便而已。
有了这个文件,咱们的查问就变成这样:
q := gplus.NewQuery[User]()
q.Eq(UserColumn.Username, “zhangsan”).Eq(UserColumn.Age,18)
users, resultDb := gplus.SelectList(q)
fmt.Println(users,resultDb.RowsAffected)
复制代码
这样保护起来就十分不便了。