大家好,我是 frank。「Golang语言开发栈」公众号作者。
01 、介绍
Go 语言微服务框架 Kratos 不限制使用任何第三方库,我们可以根据个人喜好选择第三方库。
本文我们以 XORM 和 Go Redis 为例,介绍 Kratos 微服务框架怎么集成 XORM[1] 和 Go Redis[2] 操作 MySQL 和 Redis。
02 、集成 XORM 和 Go Redis
创建项目
kratos new blog
安装 MySQL 驱动
示例代码:
go get -u github.com/go-sql-driver/mysql
安装 xorm
示例代码:
go get xorm.io/xorm
安装 go redis
示例代码:
go get github.com/redis/go-redis/v9
客户端
编写文件 blog/internal/data/data.go
。
导入第三方库
import (
_ "github.com/go-sql-driver/mysql"
"github.com/redis/go-redis/v9"
"xorm.io/xorm"
)
添加 xorm 和 go redis 客户端
// Data .
type Data struct {
// TODO wrapped database client
dbEngine *xorm.Engine
rdb *redis.Client
}
// NewData .
func NewData(c *conf.Data, logger log.Logger, dbEngin *xorm.Engine, rdb *redis.Client) (*Data, func(), error) {
cleanup := func() {
log.NewHelper(logger).Info("closing the data resources")
}
return &Data{
dbEngine: dbEngin,
rdb: rdb,
}, cleanup, nil
}
创建函数 NewDbEngine
和 NewRedisClient
func NewDbEngine(c *conf.Data) (dbEngine *xorm.Engine, err error) {
dbEngine, err = xorm.NewEngine(c.Database.Driver, c.Database.Source)
return
}
func NewRedisClient(c *conf.Data) (rdb *redis.Client) {
rdb = redis.NewClient(&redis.Options{
Addr: c.Redis.Addr,
Password: c.Redis.Password,
DB: int(c.Redis.Db),
})
return
}
添加 Wire 提供者
编写 blog/internal/data/data.go
文件,添加 NewDbEngine, NewRedisClient
。
// ProviderSet is data providers.
var ProviderSet = wire.NewSet(NewData, NewGreeterRepo, NewDbEngine, NewRedisClient)
03 、使用 XORM 和 Go Redis
我们以操作用户表 user
为例,介绍怎么使用 XORM 和 Go Redis。
数据库表 user 表结构
CREATE TABLE `user` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(30) NOT NULL DEFAULT '' COMMENT 'user name',
`email` varchar(50) NOT NULL DEFAULT '' COMMENT 'user email',
`password` varchar(30) NOT NULL DEFAULT '' COMMENT 'user password',
`created` int(11) NOT NULL DEFAULT '0' COMMENT 'create time',
`updated` int(11) NOT NULL DEFAULT '0' COMMENT 'updated time',
PRIMARY KEY (`id`),
KEY `idx_user` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='user'
首先,我们需要在 blog/internal/biz
目录中,创建文件 user.go
。
在 user.go
文件中,我们定义 User
结构体,定义 UserRepository
,定义 UserUsecase
。
定义 User
结构体
type User struct {
Id int64 `xorm:"autoincr""`
Name string
Email string
Password string
Created int64 `xorm:"created""`
Updated int64 `xorm:"updated""`
}
定义 UserRepository
type UserRepository interface {
Create(ctx context.Context, user *User) (int64, error)
Get(ctx context.Context, user *User) (bool, error)
RedisGetUser(ctx context.Context, id int64) (val string, err error)
RedisSetUser(ctx context.Context, id int64, val interface{}, expiration time.Duration) (err error)
}
定义 UserUsecase
type UserUsecase struct {
userRepo UserRepository
}
func NewUserUsecase(userRepo UserRepository) *UserUsecase {
return &UserUsecase{
userRepo: userRepo,
}
}
func (u *UserUsecase) CreateUser(ctx context.Context, user *User) (id int64, err error) {
id, err = u.userRepo.Create(ctx, user)
if err != nil {
return
}
if id > 0 {
var b []byte
b, err = json.Marshal(user)
if err != nil {
return
}
err = u.userRepo.RedisSetUser(ctx, user.Id, string(b), time.Second*300)
if err != nil {
return
}
}
return
}
添加 Wire 提供者
编写 blog/internal/biz/biz.go
文件,添加 NewUserUsecase
。
// ProviderSet is biz providers.
var ProviderSet = wire.NewSet(NewGreeterUsecase, NewUserUsecase)
然后,我们需要在 blog/internal/data
目录中,创建 user.go
文件和 redis.go
文件。
在 user.go
文件和 redis.go
文件中,我们实现 UserRepository
接口中的方法。
MySQL
type userRepository struct {
data *Data
}
func NewUserRepository(data *Data) biz.UserRepository {
return &userRepository{
data: data,
}
}
func (u *userRepository) Create(ctx context.Context, user *biz.User) (id int64, err error) {
var affected int64
affected, err = u.data.dbEngine.InsertOne(user)
if err != nil {
return
}
if affected > 0 {
id = user.Id
}
return
}
Redis
func (u *userRepository) RedisSetUser(ctx context.Context, id int64, val interface{}, expiration time.Duration) (err error) {
key := fmt.Sprintf("user:%d", id)
err = u.data.rdb.Set(ctx, key, val, expiration).Err()
if errors.Is(err, redis.Nil) {
err = nil
return
}
return
}
添加 Wire 提供者
编写 blog/internal/data/data.go
文件,添加 NewUserRepository
。
// ProviderSet is data providers.
var ProviderSet = wire.NewSet(NewData, NewGreeterRepo, NewDbEngine, NewUserRepository, NewRedisClient)
再然后,我们编辑 blog/internal/service/user.go
文件,完善该文件中的方法。
type UserService struct {
pb.UnimplementedUserServer
userUcase *biz.UserUsecase
}
func NewUserService(userUcase *biz.UserUsecase) *UserService {
return &UserService{
userUcase: userUcase,
}
}
func (s *UserService) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.CreateUserReply, error) {
user := &biz.User{
Name: req.Name,
Email: req.Email,
Password: req.Password,
}
id, err := s.userUcase.CreateUser(ctx, user)
if err != nil {
return nil, err
}
name := fmt.Sprintf("user_%d", id)
return &pb.CreateUserReply{
Name: name,
}, nil
}
添加 Wire 提供者
编写 blog/internal/service/service.go
文件,添加 NewUserService
。
// ProviderSet is service providers.
var ProviderSet = wire.NewSet(NewGreeterService, NewUserService)
最后,进入 blog/internal/server
目录,编写 http.go
和 grpc.go
文件,添加函数签名 user *service.UserService
。
并且,分别在函数体中注册服务。
示例代码:
HTTP
v1_user.RegisterUserHTTPServer(srv, user)
gRPC
v1_user.RegisterUserServer(srv, user)
Wire 生成代码
进入目录 blog/cmd/blog
,执行 wire
命令。
cd blog/cmd/blog
wire
Kratos 运行
kratos run
curl 请求示例
curl -H "Content-Type: application/json" -X POST -d '{"name":"tony", "email":"tony@gmail.com", "password":"tony"}' http://192.168.110.209:8000/user/create
04 、总结
本文我们通过示例代码,介绍 Kratos 微服务框架怎么集成第三方库,操作 MySQL 和 Redis。
参考资料
[1]
XORM: https://xorm.io/
[2]
Go Redis: https://redis.uptrace.dev/