带你十天轻松搞定 Go 微服务系列(五)
阅读原文时间:2022年01月28日阅读:2

我们通过一个系列文章跟大家详细展示一个 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

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

  • 进入服务工作区

    $ cd mall/service/order

  • 创建 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

  • 创建 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

  • 创建 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.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.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
}

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

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

!提示:启动服务需要在 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 支持我们!

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

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器