Take you ten days to easily complete the Go micro service series

preface

We will show you a go zero micro service example in detail through a series of articles. The whole series is divided into ten articles, and the directory structure is as follows:

  1. Environment construction
  2. Service splitting
  3. User services
  4. Product service
  5. Order service (this article)
  6. Payment services
  7. RPC service Auth authentication
  8. Service monitoring
  9. Link tracking
  10. Distributed transaction

This series is expected to take you to quickly develop a mall system using go zero in the Docker environment on the machine, so that you can quickly start microservices.

Complete sample code: https://github.com/nivin-studio/go-zero-mall

First, let's take a look at the overall service splitting diagram:

5 order service

  • Enter the service workspace
$ cd mall/service/order

5.1 generate order model

  • Create sql file
$ vim model/order.sql
  • Writing sql files
CREATE TABLE `order` (
	`id` bigint unsigned NOT NULL AUTO_INCREMENT,
	`uid` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'user ID',
	`pid` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'product ID',
	`amount` int(10) unsigned NOT NULL DEFAULT '0'  COMMENT 'Order amount',
	`status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Order status',
	`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;
  • Run template generation command
$ goctl model mysql ddl -src ./model/order.sql -dir ./model -c

5.2 generate order api service

  • Create api file
$ vim api/order.api
  • Writing api files
type (
	// Order creation
	CreateRequest {
		Uid    int64 `json:"uid"`
		Pid    int64 `json:"pid"`
		Amount int64 `json:"amount"`
		Status int64 `json:"status"`
	}
	CreateResponse {
		Id int64 `json:"id"`
	}
	// Order creation

	// Order modification
	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 {
	}
	// Order modification

	// Order deletion
	RemoveRequest {
		Id int64 `json:"id"`
	}
	RemoveResponse {
	}
	// Order deletion

	// Order details
	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"`
	}
	// Order details

	// Order list
	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"`
	}
	// Order list
)

@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)
}
  • Run template generation command
$ goctl api go -api ./api/order.api -dir ./api

5.3 generate order rpc service

  • Create proto file
$ vim rpc/order.proto
  • Write proto file
syntax = "proto3";

package orderclient;

option go_package = "order";

// Order creation
message CreateRequest {
    int64 Uid = 1;
    int64 Pid = 2;
    int64 Amount = 3;
    int64 Status = 4;
}
message CreateResponse {
	int64 id = 1;
}
// Order creation

// Order modification
message UpdateRequest {
    int64 id = 1;
    int64 Uid = 2;
    int64 Pid = 3;
    int64 Amount = 4;
    int64 Status = 5;
}
message UpdateResponse {
}
// Order modification

// Order deletion
message RemoveRequest {
    int64 id = 1;
}
message RemoveResponse {
}
// Order deletion

// Order details
message DetailRequest {
    int64 id = 1;
}
message DetailResponse {
    int64 id = 1;
    int64 Uid = 2;
    int64 Pid = 3;
    int64 Amount = 4;
    int64 Status = 5;
}
// Order details

// Order list
message ListRequest {
    int64 uid = 1;
}
message ListResponse {
    repeated DetailResponse data = 1;
}
// Order list

// Order payment
message PaidRequest {
    int64 id = 1;
}
message PaidResponse {
}
// Order payment

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);
}
  • Run template generation command
$ goctl rpc proto -src ./rpc/order.proto -dir ./rpc

5.4 writing order rpc service

5.4.1 modify configuration file

  • Modify order Yaml profile
$ vim rpc/etc/order.yaml
  • Modify the service listening address. The port number is 0.0.0.0:9002, Etcd service configuration, Mysql service configuration, and CacheRedis service configuration
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 add order model dependency

  • Add Mysql service configuration and instantiate CacheRedis service configuration
$ 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
}
  • Register the dependency of the service context 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 add user rpc and product rpc dependencies

  • Add user rpc, product rpc service configuration
$ 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
  • Add user RPC and instantiate the product RPC service configuration
$ 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
}
  • Register the dependency of the service context user RPC and 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 add order creation logic Create

In the order creation process, verify whether the user exists by calling the user rpc service query, and then verify whether the product exists by calling the product rpc service query, and judge whether the product inventory is sufficient. After verification, create a user order and update the product inventory by calling the product rpc service.

$ 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) {
	// Query whether the user exists
	_, err := l.svcCtx.UserRpc.UserInfo(l.ctx, &user.UserInfoRequest{
		Id: in.Uid,
	})
	if err != nil {
		return nil, err
	}

	// Query whether the product exists
	productRes, err := l.svcCtx.ProductRpc.Detail(l.ctx, &product.DetailRequest{
		Id: in.Pid,
	})
	if err != nil {
		return nil, err
	}
	// Judge whether the product inventory is sufficient
	if productRes.Stock <= 0 {
		return nil, status.Error(500, "Insufficient product inventory")
	}

	newOrder := model.Order{
		Uid:    in.Uid,
		Pid:    in.Pid,
		Amount: in.Amount,
		Status: 0,
	}
        // Create order
	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())
	}
        // Update product inventory
	_, 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
}

Note: there is a problem of data consistency in product inventory update here. In previous projects, we will use database transactions to carry out this series of operations to ensure data consistency. However, because we divide "orders" and "products" into different micro services, they may have different databases in actual projects, so we should consider ensuring data consistency in the case of Cross services, which involves the use of distributed transactions, In later chapters, we will introduce the logic of using distributed transactions to modify this order.

5.4.5 add order Detail logic 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) {
	// Query whether the order exists
	res, err := l.svcCtx.OrderModel.FindOne(in.Id)
	if err != nil {
		if err == model.ErrNotFound {
			return nil, status.Error(100, "Order does not exist")
		}
		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 add order Update logic 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) {
	// Query whether the order exists
	res, err := l.svcCtx.OrderModel.FindOne(in.Id)
	if err != nil {
		if err == model.ErrNotFound {
			return nil, status.Error(100, "Order does not exist")
		}
		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 add order delete logic 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) {
	// Query whether the order exists
	res, err := l.svcCtx.OrderModel.FindOne(in.Id)
	if err != nil {
		if err == model.ErrNotFound {
			return nil, status.Error(100, "Order does not exist")
		}
		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 add order List logic List

  • Add the OrderModel method FindAllByUid to query all orders of the user according to uid
$ 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
	}
}

......
  • Add order list logic
$ 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) {
	// Query whether the user exists
	_, err := l.svcCtx.UserRpc.UserInfo(l.ctx, &user.UserInfoRequest{
		Id: in.Uid,
	})
	if err != nil {
		return nil, err
	}

	// Query whether the order exists
	list, err := l.svcCtx.OrderModel.FindAllByUid(in.Uid)
	if err != nil {
		if err == model.ErrNotFound {
			return nil, status.Error(100, "Order does not exist")
		}
		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 add order payment logic 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) {
	// Query whether the order exists
	res, err := l.svcCtx.OrderModel.FindOne(in.Id)
	if err != nil {
		if err == model.ErrNotFound {
			return nil, status.Error(100, "Order does not exist")
		}
		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 writing order api service

5.5.1 modify configuration file

  • Modify order Yaml profile
$ vim api/etc/order.yaml
  • Modify the service address, the port number is 0.0.0.0:8002, the Mysql service configuration, the CacheRedis service configuration, and the Auth authentication configuration
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 add order rpc dependency

  • Add order rpc service configuration
$ vim api/etc/order.yaml
Name: Order
Host: 0.0.0.0
Port: 8002

......

OrderRpc:
  Etcd:
    Hosts:
    - etcd:2379
    Key: order.rpc
  • Add instantiation of order rpc service configuration
$ 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
}
  • Register service context user rpc dependency
$ 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 add order creation logic

$ 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 add order Detail logic 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 add order Update logic 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 add order delete logic 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 add order List logic 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 start order rpc service

Tip: start the service in the golang container

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

5.7 start order api service

Tip: start the service in the golang container

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

Project address

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

https://gitee.com/kevwan/go-zero

Welcome to go zero and star support us!

Wechat communication group

Focus on the "micro service practice" official account and click on the exchange group to get the community community's two-dimensional code.

Keywords: MySQL github bash yaml etcd

Added by Dat on Sat, 22 Jan 2022 05:45:50 +0200