背景
去年渐渐开始触摸了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.SelectById[User](1)
fmt.Println(user, resultDb.RowsAffected)
根据ids查询:
var ids = []int{1,2}
users, resultDb := gplus.SelectByIds[User](ids)
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)
这样保护起来就十分便利了。
最后
更多的用法请检查github地址:
github.com/acmestack/g…
感兴趣的,动动小手指,点个star哈!
代码现已重构,不在需求gplus东西生成字段了,经过指针字段查询就能够了,再也不用忧虑会写错字段名了,最新用法请检查Github的README文档。
更新于2023-02-09