• 带你十天轻松搞定 Go 微服务系列(五)


    序言

    我们通过一个系列文章跟大家详细展示一个 go-zero 微服务示例,整个系列分十篇文章,目录结构如下:

    1. 环境搭建
    2. 服务拆分
    3. 用户服务
    4. 产品服务
    5. 订单服务(本文)
    6. 支付服务
    7. RPC 服务 Auth 验证
    8. 服务监控
    9. 链路追踪
    10. 分布式事务

    期望通过本系列带你在本机利用 Docker 环境利用 go-zero 快速开发一个商城系统,让你快速上手微服务。

    完整示例代码:https://github.com/nivin-studio/go-zero-mall

    首先,我们来看一下整体的服务拆分图:

    5 订单服务(order)

    • 进入服务工作区
    $ cd mall/service/order
    

    5.1 生成 order model 模型

    • 创建 sql 文件
    $ vim model/order.sql
    
    • 编写 sql 文件
    CREATE TABLE `order` (
    	`id` bigint unsigned NOT NULL AUTO_INCREMENT,
    	`uid` bigint unsigned NOT NULL DEFAULT '0' COMMENT '用户ID',
    	`pid` bigint unsigned NOT NULL DEFAULT '0' COMMENT '产品ID',
    	`amount` int(10) unsigned NOT NULL DEFAULT '0'  COMMENT '订单金额',
    	`status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '订单状态',
    	`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
    	`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    	PRIMARY KEY (`id`),
    	KEY `idx_uid` (`uid`),
    	KEY `idx_pid` (`pid`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;
    
    • 运行模板生成命令
    $ goctl model mysql ddl -src ./model/order.sql -dir ./model -c
    

    5.2 生成 order api 服务

    • 创建 api 文件
    $ vim api/order.api
    
    • 编写 api 文件
    type (
    	// 订单创建
    	CreateRequest {
    		Uid    int64 `json:"uid"`
    		Pid    int64 `json:"pid"`
    		Amount int64 `json:"amount"`
    		Status int64 `json:"status"`
    	}
    	CreateResponse {
    		Id int64 `json:"id"`
    	}
    	// 订单创建
    
    	// 订单修改
    	UpdateRequest {
    		Id     int64 `json:"id"`
    		Uid    int64 `json:"uid,optional"`
    		Pid    int64 `json:"pid,optional"`
    		Amount int64 `json:"amount,optional"`
    		Status int64 `json:"status,optional"`
    	}
    	UpdateResponse {
    	}
    	// 订单修改
    
    	// 订单删除
    	RemoveRequest {
    		Id int64 `json:"id"`
    	}
    	RemoveResponse {
    	}
    	// 订单删除
    
    	// 订单详情
    	DetailRequest {
    		Id int64 `json:"id"`
    	}
    	DetailResponse {
    		Id     int64 `json:"id"`
    		Uid    int64 `json:"uid"`
    		Pid    int64 `json:"pid"`
    		Amount int64 `json:"amount"`
    		Status int64 `json:"status"`
    	}
    	// 订单详情
    
    	// 订单列表
    	ListRequest {
    		Uid int64 `json:"uid"`
    	}
    	ListResponse {
    		Id     int64 `json:"id"`
    		Uid    int64 `json:"uid"`
    		Pid    int64 `json:"pid"`
    		Amount int64 `json:"amount"`
    		Status int64 `json:"status"`
    	}
    	// 订单列表
    )
    
    @server(
    	jwt: Auth
    )
    service Order {
    	@handler Create
    	post /api/order/create(CreateRequest) returns (CreateResponse)
    	
    	@handler Update
    	post /api/order/update(UpdateRequest) returns (UpdateResponse)
    	
    	@handler Remove
    	post /api/order/remove(RemoveRequest) returns (RemoveResponse)
    	
    	@handler Detail
    	post /api/order/detail(DetailRequest) returns (DetailResponse)
    	
    	@handler List
    	post /api/order/list(ListRequest) returns (ListResponse)
    }
    
    • 运行模板生成命令
    $ goctl api go -api ./api/order.api -dir ./api
    

    5.3 生成 order rpc 服务

    • 创建 proto 文件
    $ vim rpc/order.proto
    
    • 编写 proto 文件
    syntax = "proto3";
    
    package orderclient;
    
    option go_package = "order";
    
    // 订单创建
    message CreateRequest {
        int64 Uid = 1;
        int64 Pid = 2;
        int64 Amount = 3;
        int64 Status = 4;
    }
    message CreateResponse {
    	int64 id = 1;
    }
    // 订单创建
    
    // 订单修改
    message UpdateRequest {
        int64 id = 1;
        int64 Uid = 2;
        int64 Pid = 3;
        int64 Amount = 4;
        int64 Status = 5;
    }
    message UpdateResponse {
    }
    // 订单修改
    
    // 订单删除
    message RemoveRequest {
        int64 id = 1;
    }
    message RemoveResponse {
    }
    // 订单删除
    
    // 订单详情
    message DetailRequest {
        int64 id = 1;
    }
    message DetailResponse {
        int64 id = 1;
        int64 Uid = 2;
        int64 Pid = 3;
        int64 Amount = 4;
        int64 Status = 5;
    }
    // 订单详情
    
    // 订单列表
    message ListRequest {
        int64 uid = 1;
    }
    message ListResponse {
        repeated DetailResponse data = 1;
    }
    // 订单列表
    
    // 订单支付
    message PaidRequest {
        int64 id = 1;
    }
    message PaidResponse {
    }
    // 订单支付
    
    service Order {
        rpc Create(CreateRequest) returns(CreateResponse);
        rpc Update(UpdateRequest) returns(UpdateResponse);
        rpc Remove(RemoveRequest) returns(RemoveResponse);
        rpc Detail(DetailRequest) returns(DetailResponse);
        rpc List(ListRequest) returns(ListResponse);
        rpc Paid(PaidRequest) returns(PaidResponse);
    }
    
    • 运行模板生成命令
    $ goctl rpc proto -src ./rpc/order.proto -dir ./rpc
    

    5.4 编写 order rpc 服务

    5.4.1 修改配置文件

    • 修改 order.yaml 配置文件
    $ vim rpc/etc/order.yaml
    
    • 修改服务监听地址,端口号为0.0.0.0:9002,Etcd 服务配置,Mysql 服务配置,CacheRedis 服务配置
    Name: order.rpc
    ListenOn: 0.0.0.0:9002
    
    Etcd:
      Hosts:
      - etcd:2379
      Key: order.rpc
    
    Mysql:
      DataSource: root:123456@tcp(mysql:3306)/mall?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
    
    CacheRedis:
    - Host: redis:6379
      Type: node
      Pass:
    

    5.4.2 添加 order model 依赖

    • 添加 Mysql 服务配置,CacheRedis 服务配置的实例化
    $ vim rpc/internal/config/config.go
    
    package config
    
    import (
    	"github.com/tal-tech/go-zero/core/stores/cache"
    	"github.com/tal-tech/go-zero/zrpc"
    )
    
    type Config struct {
    	zrpc.RpcServerConf
    
    	Mysql struct {
    		DataSource string
    	}
        
    	CacheRedis cache.CacheConf
    }
    
    • 注册服务上下文 order model 的依赖
    $ vim rpc/internal/svc/servicecontext.go
    
    package svc
    
    import (
    	"mall/service/order/model"
    	"mall/service/order/rpc/internal/config"
    
    	"github.com/tal-tech/go-zero/core/stores/sqlx"
    )
    
    type ServiceContext struct {
    	Config config.Config
    
    	OrderModel model.OrderModel
    }
    
    func NewServiceContext(c config.Config) *ServiceContext {
    	conn := sqlx.NewMysql(c.Mysql.DataSource)
    	return &ServiceContext{
    		Config:     c,
    		OrderModel: model.NewOrderModel(conn, c.CacheRedis),
    	}
    }
    

    5.4.3 添加 user rpc,product rpc 依赖

    • 添加 user rpc, product rpc 服务配置
    $ vim rpc/etc/order.yaml
    
    Name: order.rpc
    ListenOn: 0.0.0.0:9002
    Etcd:
      Hosts:
      - etcd:2379
      Key: order.rpc
      
    ......
    
    UserRpc:
      Etcd:
        Hosts:
        - etcd:2379
        Key: user.rpc
    
    ProductRpc:
      Etcd:
        Hosts:
        - etcd:2379
        Key: product.rpc
    
    • 添加 user rpc, product rpc 服务配置的实例化
    $ vim rpc/internal/config/config.go
    
    package config
    
    import (
    	"github.com/tal-tech/go-zero/core/stores/cache"
    	"github.com/tal-tech/go-zero/zrpc"
    )
    
    type Config struct {
    	zrpc.RpcServerConf
    
    	Mysql struct {
    		DataSource string
    	}
        
    	CacheRedis cache.CacheConf
    
    	UserRpc    zrpc.RpcClientConf
    	ProductRpc zrpc.RpcClientConf
    }
    
    • 注册服务上下文 user rpc, product rpc 的依赖
    $ vim rpc/internal/svc/servicecontext.go
    
    package svc
    
    import (
    	"mall/service/order/model"
    	"mall/service/order/rpc/internal/config"
    	"mall/service/product/rpc/productclient"
    	"mall/service/user/rpc/userclient"
    
    	"github.com/tal-tech/go-zero/core/stores/sqlx"
    	"github.com/tal-tech/go-zero/zrpc"
    )
    
    type ServiceContext struct {
    	Config config.Config
    
    	OrderModel model.OrderModel
    
    	UserRpc    userclient.User
    	ProductRpc productclient.Product
    }
    
    func NewServiceContext(c config.Config) *ServiceContext {
    	conn := sqlx.NewMysql(c.Mysql.DataSource)
    	return &ServiceContext{
    		Config:     c,
    		OrderModel: model.NewOrderModel(conn, c.CacheRedis),
    		UserRpc:    userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),
    		ProductRpc: productclient.NewProduct(zrpc.MustNewClient(c.ProductRpc)),
    	}
    }
    

    5.4.4 添加订单创建逻辑 Create

    订单创建流程,通过调用 user rpc 服务查询验证用户是否存在,再通过调用 product rpc 服务查询验证产品是否存在,以及判断产品库存是否充足。验证通过后,创建用户订单,并通过调用 product rpc 服务更新产品库存。

    $ vim rpc/internal/logic/createlogic.go
    
    package logic
    
    import (
    	"context"
    
    	"mall/service/order/model"
    	"mall/service/order/rpc/internal/svc"
    	"mall/service/order/rpc/order"
    	"mall/service/product/rpc/product"
    	"mall/service/user/rpc/user"
    
    	"github.com/tal-tech/go-zero/core/logx"
    	"google.golang.org/grpc/status"
    )
    
    type CreateLogic struct {
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    	logx.Logger
    }
    
    func NewCreateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateLogic {
    	return &CreateLogic{
    		ctx:    ctx,
    		svcCtx: svcCtx,
    		Logger: logx.WithContext(ctx),
    	}
    }
    
    func (l *CreateLogic) Create(in *order.CreateRequest) (*order.CreateResponse, error) {
    	// 查询用户是否存在
    	_, err := l.svcCtx.UserRpc.UserInfo(l.ctx, &user.UserInfoRequest{
    		Id: in.Uid,
    	})
    	if err != nil {
    		return nil, err
    	}
    
    	// 查询产品是否存在
    	productRes, err := l.svcCtx.ProductRpc.Detail(l.ctx, &product.DetailRequest{
    		Id: in.Pid,
    	})
    	if err != nil {
    		return nil, err
    	}
    	// 判断产品库存是否充足
    	if productRes.Stock <= 0 {
    		return nil, status.Error(500, "产品库存不足")
    	}
    
    	newOrder := model.Order{
    		Uid:    in.Uid,
    		Pid:    in.Pid,
    		Amount: in.Amount,
    		Status: 0,
    	}
            // 创建订单
    	res, err := l.svcCtx.OrderModel.Insert(&newOrder)
    	if err != nil {
    		return nil, status.Error(500, err.Error())
    	}
    
    	newOrder.Id, err = res.LastInsertId()
    	if err != nil {
    		return nil, status.Error(500, err.Error())
    	}
            // 更新产品库存
    	_, err = l.svcCtx.ProductRpc.Update(l.ctx, &product.UpdateRequest{
    		Id:     productRes.Id,
    		Name:   productRes.Name,
    		Desc:   productRes.Desc,
                    Stock:  productRes.Stock - 1,
    		Amount: productRes.Amount,
    		Status: productRes.Status,
    	})
    	if err != nil {
    		return nil, err
    	}
    
    	return &order.CreateResponse{
    		Id: newOrder.Id,
    	}, nil
    }
    

    !注意:这里的产品库存更新存在数据一致性问题,在以往的项目中我们会使用数据库的事务进行这一系列的操作来保证数据的一致性。但是因为我们这边把“订单”和“产品”分成了不同的微服务,在实际的项目中他们可能拥有不同的数据库,所以我们要考虑在跨服务的情况下还能保证数据的一致性,这就涉及到了分布式事务的使用,在后面的章节中我们将介绍使用分布式事务来修改这个下单的逻辑。

    5.4.5 添加订单详情逻辑 Detail

    $ vim rpc/internal/logic/detaillogic.go
    
    package logic
    
    import (
    	"context"
    
    	"mall/service/order/model"
    	"mall/service/order/rpc/internal/svc"
    	"mall/service/order/rpc/order"
    
    	"github.com/tal-tech/go-zero/core/logx"
    	"google.golang.org/grpc/status"
    )
    
    type DetailLogic struct {
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    	logx.Logger
    }
    
    func NewDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DetailLogic {
    	return &DetailLogic{
    		ctx:    ctx,
    		svcCtx: svcCtx,
    		Logger: logx.WithContext(ctx),
    	}
    }
    
    func (l *DetailLogic) Detail(in *order.DetailRequest) (*order.DetailResponse, error) {
    	// 查询订单是否存在
    	res, err := l.svcCtx.OrderModel.FindOne(in.Id)
    	if err != nil {
    		if err == model.ErrNotFound {
    			return nil, status.Error(100, "订单不存在")
    		}
    		return nil, status.Error(500, err.Error())
    	}
    
    	return &order.DetailResponse{
    		Id:     res.Id,
    		Uid:    res.Uid,
    		Pid:    res.Pid,
    		Amount: res.Amount,
    		Status: res.Status,
    	}, nil
    }
    

    5.4.6 添加订单更新逻辑 Update

    $ vim rpc/internal/logic/updatelogic.go
    
    package logic
    
    import (
    	"context"
    
    	"mall/service/order/model"
    	"mall/service/order/rpc/internal/svc"
    	"mall/service/order/rpc/order"
    
    	"github.com/tal-tech/go-zero/core/logx"
    	"google.golang.org/grpc/status"
    )
    
    type UpdateLogic struct {
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    	logx.Logger
    }
    
    func NewUpdateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateLogic {
    	return &UpdateLogic{
    		ctx:    ctx,
    		svcCtx: svcCtx,
    		Logger: logx.WithContext(ctx),
    	}
    }
    
    func (l *UpdateLogic) Update(in *order.UpdateRequest) (*order.UpdateResponse, error) {
    	// 查询订单是否存在
    	res, err := l.svcCtx.OrderModel.FindOne(in.Id)
    	if err != nil {
    		if err == model.ErrNotFound {
    			return nil, status.Error(100, "订单不存在")
    		}
    		return nil, status.Error(500, err.Error())
    	}
    
    	if in.Uid != 0 {
    		res.Uid = in.Uid
    	}
    	if in.Pid != 0 {
    		res.Pid = in.Pid
    	}
    	if in.Amount != 0 {
    		res.Amount = in.Amount
    	}
    	if in.Status != 0 {
    		res.Status = in.Status
    	}
    
    	err = l.svcCtx.OrderModel.Update(res)
    	if err != nil {
    		return nil, status.Error(500, err.Error())
    	}
    
    	return &order.UpdateResponse{}, nil
    }
    

    5.4.7 添加订单删除逻辑 Remove

    $ vim rpc/internal/logic/removelogic.go
    
    package logic
    
    import (
    	"context"
    
    	"mall/service/order/model"
    	"mall/service/order/rpc/internal/svc"
    	"mall/service/order/rpc/order"
    
    	"github.com/tal-tech/go-zero/core/logx"
    	"google.golang.org/grpc/status"
    )
    
    type RemoveLogic struct {
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    	logx.Logger
    }
    
    func NewRemoveLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RemoveLogic {
    	return &RemoveLogic{
    		ctx:    ctx,
    		svcCtx: svcCtx,
    		Logger: logx.WithContext(ctx),
    	}
    }
    
    func (l *RemoveLogic) Remove(in *order.RemoveRequest) (*order.RemoveResponse, error) {
    	// 查询订单是否存在
    	res, err := l.svcCtx.OrderModel.FindOne(in.Id)
    	if err != nil {
    		if err == model.ErrNotFound {
    			return nil, status.Error(100, "订单不存在")
    		}
    		return nil, status.Error(500, err.Error())
    	}
    
    	err = l.svcCtx.OrderModel.Delete(res.Id)
    	if err != nil {
    		return nil, status.Error(500, err.Error())
    	}
    
    	return &order.RemoveResponse{}, nil
    }
    

    5.4.8 添加订单列表逻辑 List

    • 添加根据 uid 查询用户所有订单的 OrderModel 方法 FindAllByUid
    $ vim model/ordermodel.go
    
    package model
    
    ......
    
    type (
    	OrderModel interface {
    		Insert(data *Order) (sql.Result, error)
    		FindOne(id int64) (*Order, error)
    		FindAllByUid(uid int64) ([]*Order, error)
    		Update(data *Order) error
    		Delete(id int64) error
    	}
    
    	......
    )
    
    ......
    
    func (m *defaultOrderModel) FindAllByUid(uid int64) ([]*Order, error) {
    	var resp []*Order
    
    	query := fmt.Sprintf("select %s from %s where `uid` = ?", orderRows, m.table)
    	err := m.QueryRowsNoCache(&resp, query, uid)
    
    	switch err {
    	case nil:
    		return resp, nil
    	case sqlc.ErrNotFound:
    		return nil, ErrNotFound
    	default:
    		return nil, err
    	}
    }
    
    ......
    
    • 添加订单列表逻辑
    $ vim rpc/internal/logic/listlogic.go
    
    package logic
    
    import (
    	"context"
    
    	"mall/service/order/model"
    	"mall/service/order/rpc/internal/svc"
    	"mall/service/order/rpc/order"
    	"mall/service/user/rpc/user"
    
    	"github.com/tal-tech/go-zero/core/logx"
    	"google.golang.org/grpc/status"
    )
    
    type ListLogic struct {
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    	logx.Logger
    }
    
    func NewListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListLogic {
    	return &ListLogic{
    		ctx:    ctx,
    		svcCtx: svcCtx,
    		Logger: logx.WithContext(ctx),
    	}
    }
    
    func (l *ListLogic) List(in *order.ListRequest) (*order.ListResponse, error) {
    	// 查询用户是否存在
    	_, err := l.svcCtx.UserRpc.UserInfo(l.ctx, &user.UserInfoRequest{
    		Id: in.Uid,
    	})
    	if err != nil {
    		return nil, err
    	}
    
    	// 查询订单是否存在
    	list, err := l.svcCtx.OrderModel.FindAllByUid(in.Uid)
    	if err != nil {
    		if err == model.ErrNotFound {
    			return nil, status.Error(100, "订单不存在")
    		}
    		return nil, status.Error(500, err.Error())
    	}
    
    	orderList := make([]*order.DetailResponse, 0)
    	for _, item := range list {
    		orderList = append(orderList, &order.DetailResponse{
    			Id:     item.Id,
    			Uid:    item.Uid,
    			Pid:    item.Pid,
    			Amount: item.Amount,
    			Status: item.Status,
    		})
    	}
    
    	return &order.ListResponse{
    		Data: orderList,
    	}, nil
    }
    

    5.4.9 添加订单支付逻辑 Paid

    $ vim rpc/internal/logic/paidlogic.go
    
    package logic
    
    import (
    	"context"
    
    	"mall/service/order/model"
    	"mall/service/order/rpc/internal/svc"
    	"mall/service/order/rpc/order"
    
    	"github.com/tal-tech/go-zero/core/logx"
    	"google.golang.org/grpc/status"
    )
    
    type PaidLogic struct {
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    	logx.Logger
    }
    
    func NewPaidLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PaidLogic {
    	return &PaidLogic{
    		ctx:    ctx,
    		svcCtx: svcCtx,
    		Logger: logx.WithContext(ctx),
    	}
    }
    
    func (l *PaidLogic) Paid(in *order.PaidRequest) (*order.PaidResponse, error) {
    	// 查询订单是否存在
    	res, err := l.svcCtx.OrderModel.FindOne(in.Id)
    	if err != nil {
    		if err == model.ErrNotFound {
    			return nil, status.Error(100, "订单不存在")
    		}
    		return nil, status.Error(500, err.Error())
    	}
    
    	res.Status = 1
    
    	err = l.svcCtx.OrderModel.Update(res)
    	if err != nil {
    		return nil, status.Error(500, err.Error())
    	}
    
    	return &order.PaidResponse{}, nil
    }
    

    5.5 编写 order api 服务

    5.5.1 修改配置文件

    • 修改 order.yaml 配置文件
    $ vim api/etc/order.yaml
    
    • 修改服务地址,端口号为0.0.0.0:8002,Mysql 服务配置,CacheRedis 服务配置,Auth 验证配置
    Name: Order
    Host: 0.0.0.0
    Port: 8002
    
    Mysql:
      DataSource: root:123456@tcp(mysql:3306)/mall?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
    
    CacheRedis:
    - Host: redis:6379
      Type: node
      Pass:
    
    Auth:
      AccessSecret: uOvKLmVfztaXGpNYd4Z0I1SiT7MweJhl
      AccessExpire: 86400
    

    5.5.2 添加 order rpc 依赖

    • 添加 order rpc 服务配置
    $ vim api/etc/order.yaml
    
    Name: Order
    Host: 0.0.0.0
    Port: 8002
    
    ......
    
    OrderRpc:
      Etcd:
        Hosts:
        - etcd:2379
        Key: order.rpc
    
    • 添加 order rpc 服务配置的实例化
    $ vim api/internal/config/config.go
    
    package config
    
    import (
    	"github.com/tal-tech/go-zero/rest"
    	"github.com/tal-tech/go-zero/zrpc"
    )
    
    type Config struct {
    	rest.RestConf
    
    	Auth struct {
    		AccessSecret string
    		AccessExpire int64
    	}
    
    	OrderRpc zrpc.RpcClientConf
    }
    
    • 注册服务上下文 user rpc 的依赖
    $ vim api/internal/svc/servicecontext.go
    
    package svc
    
    import (
    	"mall/service/order/api/internal/config"
    	"mall/service/order/rpc/orderclient"
    
    	"github.com/tal-tech/go-zero/zrpc"
    )
    
    type ServiceContext struct {
    	Config config.Config
    
    	OrderRpc orderclient.Order
    }
    
    func NewServiceContext(c config.Config) *ServiceContext {
    	return &ServiceContext{
    		Config:   c,
    		OrderRpc: orderclient.NewOrder(zrpc.MustNewClient(c.OrderRpc)),
    	}
    }
    

    5.5.3 添加订单创建逻辑 Create

    $ vim api/internal/logic/createlogic.go
    
    package logic
    
    import (
    	"context"
    
    	"mall/service/order/api/internal/svc"
    	"mall/service/order/api/internal/types"
    	"mall/service/order/rpc/orderclient"
    
    	"github.com/tal-tech/go-zero/core/logx"
    )
    
    type CreateLogic struct {
    	logx.Logger
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    }
    
    func NewCreateLogic(ctx context.Context, svcCtx *svc.ServiceContext) CreateLogic {
    	return CreateLogic{
    		Logger: logx.WithContext(ctx),
    		ctx:    ctx,
    		svcCtx: svcCtx,
    	}
    }
    
    func (l *CreateLogic) Create(req types.CreateRequest) (resp *types.CreateResponse, err error) {
    	res, err := l.svcCtx.OrderRpc.Create(l.ctx, &orderclient.CreateRequest{
    		Uid:    req.Uid,
    		Pid:    req.Pid,
    		Amount: req.Amount,
    		Status: req.Status,
    	})
    	if err != nil {
    		return nil, err
    	}
    
    	return &types.CreateResponse{
    		Id: res.Id,
    	}, nil
    }
    

    5.5.4 添加订单详情逻辑 Detail

    $ vim api/internal/logic/detaillogic.go
    
    package logic
    
    import (
    	"context"
    
    	"mall/service/order/api/internal/svc"
    	"mall/service/order/api/internal/types"
    	"mall/service/order/rpc/orderclient"
    
    	"github.com/tal-tech/go-zero/core/logx"
    )
    
    type DetailLogic struct {
    	logx.Logger
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    }
    
    func NewDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) DetailLogic {
    	return DetailLogic{
    		Logger: logx.WithContext(ctx),
    		ctx:    ctx,
    		svcCtx: svcCtx,
    	}
    }
    
    func (l *DetailLogic) Detail(req types.DetailRequest) (resp *types.DetailResponse, err error) {
    	res, err := l.svcCtx.OrderRpc.Detail(l.ctx, &orderclient.DetailRequest{
    		Id: req.Id,
    	})
    	if err != nil {
    		return nil, err
    	}
    
    	return &types.DetailResponse{
    		Id:     res.Id,
    		Uid:    res.Uid,
    		Pid:    res.Pid,
    		Amount: res.Amount,
    		Status: res.Status,
    	}, nil
    }
    

    5.5.5 添加订单更新逻辑 Update

    $ vim api/internal/logic/updatelogic.go
    
    package logic
    
    import (
    	"context"
    
    	"mall/service/order/api/internal/svc"
    	"mall/service/order/api/internal/types"
    	"mall/service/order/rpc/orderclient"
    
    	"github.com/tal-tech/go-zero/core/logx"
    )
    
    type UpdateLogic struct {
    	logx.Logger
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    }
    
    func NewUpdateLogic(ctx context.Context, svcCtx *svc.ServiceContext) UpdateLogic {
    	return UpdateLogic{
    		Logger: logx.WithContext(ctx),
    		ctx:    ctx,
    		svcCtx: svcCtx,
    	}
    }
    
    func (l *UpdateLogic) Update(req types.UpdateRequest) (resp *types.UpdateResponse, err error) {
    	_, err = l.svcCtx.OrderRpc.Update(l.ctx, &orderclient.UpdateRequest{
    		Id:     req.Id,
    		Uid:    req.Uid,
    		Pid:    req.Pid,
    		Amount: req.Amount,
    		Status: req.Status,
    	})
    	if err != nil {
    		return nil, err
    	}
    
    	return &types.UpdateResponse{}, nil
    }
    

    5.5.6 添加订单删除逻辑 Remove

    $ vim api/internal/logic/removelogic.go
    
    package logic
    
    import (
    	"context"
    
    	"mall/service/order/api/internal/svc"
    	"mall/service/order/api/internal/types"
    	"mall/service/order/rpc/orderclient"
    
    	"github.com/tal-tech/go-zero/core/logx"
    )
    
    type RemoveLogic struct {
    	logx.Logger
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    }
    
    func NewRemoveLogic(ctx context.Context, svcCtx *svc.ServiceContext) RemoveLogic {
    	return RemoveLogic{
    		Logger: logx.WithContext(ctx),
    		ctx:    ctx,
    		svcCtx: svcCtx,
    	}
    }
    
    func (l *RemoveLogic) Remove(req types.RemoveRequest) (resp *types.RemoveResponse, err error) {
    	_, err = l.svcCtx.OrderRpc.Remove(l.ctx, &orderclient.RemoveRequest{
    		Id: req.Id,
    	})
    	if err != nil {
    		return nil, err
    	}
    
    	return &types.RemoveResponse{}, nil
    }
    

    5.5.7 添加订单列表逻辑 List

    $ vim api/internal/logic/listlogic.go
    
    package logic
    
    import (
    	"context"
    
    	"mall/service/order/api/internal/svc"
    	"mall/service/order/api/internal/types"
    	"mall/service/order/rpc/orderclient"
    
    	"github.com/tal-tech/go-zero/core/logx"
    )
    
    type ListLogic struct {
    	logx.Logger
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    }
    
    func NewListLogic(ctx context.Context, svcCtx *svc.ServiceContext) ListLogic {
    	return ListLogic{
    		Logger: logx.WithContext(ctx),
    		ctx:    ctx,
    		svcCtx: svcCtx,
    	}
    }
    
    func (l *ListLogic) List(req types.ListRequest) (resp []*types.ListResponse, err error) {
    	res, err := l.svcCtx.OrderRpc.List(l.ctx, &orderclient.ListRequest{
    		Uid: req.Uid,
    	})
    	if err != nil {
    		return nil, err
    	}
    
    	orderList := make([]*types.ListResponse, 0)
    	for _, item := range res.Data {
    		orderList = append(orderList, &types.ListResponse{
    			Id:     item.Id,
    			Uid:    item.Uid,
    			Pid:    item.Pid,
    			Amount: item.Amount,
    			Status: item.Status,
    		})
    	}
    
    	return orderList, nil
    }
    

    5.6 启动 order rpc 服务

    !提示:启动服务需要在 golang 容器中启动

    $ cd mall/service/order/rpc
    $ go run order.go -f etc/order.yaml
    Starting rpc server at 127.0.0.1:9002...
    

    5.7 启动 order api 服务

    !提示:启动服务需要在 golang 容器中启动

    $ cd mall/service/order/api
    $ go run order.go -f etc/order.yaml
    Starting server at 0.0.0.0:8002...
    

    项目地址

    https://github.com/zeromicro/go-zero

    欢迎使用 go-zerostar 支持我们!

    微信交流群

    关注『微服务实践』公众号并点击 交流群 获取社区群二维码。

  • 相关阅读:
    通过TortoiseGit上传项目到GitHub
    删除右键菜单中的Git Gui Here、Git Bash Here的方法
    block functions区块函数插件的定义与使用
    modifiers标量调节器插件的定义和使用
    functions函数插件的定义和使用
    smarty内置函数、自定义函数
    smarty类与对象的赋值与使用
    Smarty模板的引用
    Smarty的循环
    Smarty的条件判断语句
  • 原文地址:https://www.cnblogs.com/kevinwan/p/15849077.html
Copyright © 2020-2023  润新知