商品服务
生成基于 go-zero+gorm+ddd 的商品服务 demo
0.初始化
安装goctl protoc 工具,
生成gorm的模型需要替换goctl,版本分支 goctl138
github.com/tiptok/go-z…
1.建表
mkdir -p deploy/sql/product
touch deploy/sql/product/000001_create_product_table.up.sql
sql文件内容如下:
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
price DECIMAL(10, 2) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted_at timestamp null,
version bigint default 0
);
touch deploy/sql/product/000001_create_product_table.down.sql
sql文件内容如下:
drop table if exists product;
生成模型
goctl model mysql ddl -s deploy/sql/product/000001_create_product_table.up.sql -d app/product
2.编写proto文件
mkdir -p api/protobuf/product/v1
touch api/protobuf/product/v1/product.proto
proto文件如下:
syntax = "proto3";
package api.protobuf.product.v1;
option go_package = "../v1";
message Product {
int64 id = 1;
string name = 2;
string description = 3;
float price = 4;
string unit = 5;
int64 stock = 6;
int64 created_at = 7;
int64 updated_at = 8;
}
message CreateProductRequest {
Product product = 1;
}
message CreateProductResponse {
Product product = 1;
}
message UpdateProductRequest {
Product product = 1;
}
message UpdateProductResponse {
bool success = 1;
}
message GetProductRequest {
int64 id = 1;
}
message GetProductResponse {
Product product = 1;
}
message DeleteProductRequest {
uint64 id = 1;
}
message DeleteProductResponse {
bool success = 1;
}
message ListProductsRequest {
int32 offset = 1;
int32 limit = 2;
}
message ListProductsResponse {
repeated Product products = 1;
uint64 count = 2;
}
service ProductService {
rpc GetProduct(GetProductRequest) returns (GetProductResponse) {}
rpc CreateProduct(CreateProductRequest) returns (CreateProductResponse) {}
rpc UpdateProduct(UpdateProductRequest) returns (UpdateProductResponse) {}
rpc DeleteProduct(DeleteProductRequest) returns (DeleteProductResponse) {}
rpc ListProducts(ListProductsRequest) returns (ListProductsResponse) {}
}
生成服务
goctl rpc protoc api/protobuf/product/v1/*.proto --go_out=./api/protobuf/product/v1 --go-grpc_out=./api/protobuf/product/v1 --zrpc_out=app/product/cmd/rpc
生成服务代码目录
3.填写业务逻辑
初始化服务实例,配置多级缓存插件
func NewServiceContext(c config.Config) *ServiceContext {
db := database.OpenGormDB(c.DB.DataSource)
mlCache := cache.NewMultiLevelCache([]string{c.Redis.Host}, c.Redis.Pass)
return &ServiceContext{
Config: c,
DB: db,
ProductsRepository: repository.NewProductsRepository(cache.NewCachedRepository(mlCache)),
}
}
调用服务实例,开启事务创建产品添加到数据库表内
func (l *CreateProductLogic) CreateProduct(in *v1.CreateProductRequest) (*v1.CreateProductResponse, error) {
product := &domain.Products{
Name: in.GetProduct().Name,
Description: in.GetProduct().Description,
Price: in.GetProduct().Price,
Unit: in.GetProduct().Unit,
Stock: in.GetProduct().Stock,
}
var err error
if err = transaction.UseTrans(l.ctx, l.svcCtx.DB, func(ctx context.Context, conn transaction.Conn) error {
product, err = l.svcCtx.ProductsRepository.Insert(l.ctx, conn, product)
return err
}, true); err != nil {
return nil, status.Errorf(codes.Internal, "failed to create product: %v", err)
}
return &v1.CreateProductResponse{
Product: productservice.ProductEntityToProtobuf(product),
}, nil
}
查询商品详情
func (l *GetProductLogic) GetProduct(in *v1.GetProductRequest) (*v1.GetProductResponse, error) {
conn := l.svcCtx.DefaultDBConn()
product, err := l.svcCtx.ProductsRepository.FindOne(l.ctx, conn, in.GetId())
if err != nil {
return nil, status.Error(codes.NotFound, fmt.Sprintf("not found product id %v", in.GetId()))
}
return &v1.GetProductResponse{
Product: productservice.ProductEntityToProtobuf(product),
}, nil
}
接口调用
- BloomRpc 应答里面float精度显示不正常(软件问题),grpcui下正常
- grpcui 需要开启grpc 服务反射功能,go-zero 配置 Mode:dev
go install github.com/fullstorydev/grpcui/cmd/grpcui@latest
grpcui -plaintext localhost:8080