See how my Go-zero challenge makes it even simpler
For many startups, we must always focus extra on delivering the merchandise within the early stage of enterprise. The monolithic companies have the benefits of easy structure, simple deployment, and higher improvement productiveness, which can assist us obtain the product necessities shortly. Whereas we use monolithic companies to ship merchandise shortly, we additionally want to order the chance for enterprise increment, so we normally break up completely different enterprise modules clearly in monolithic companies.
We take the mall for example to construct a monolithic service. The mall service is mostly comparatively advanced and consists of a number of modules, the extra vital modules embrace account, product and order modules, and many others. Every module can have its personal impartial enterprise logic, and every module will even depend upon some others. For instance, the order module and the product module will depend upon the account module. Within the monolithic utility this type of dependency is normally achieved by technique calls between modules. Monolithic companies typically share storage sources, corresponding to MySQL
and Redis
.
The general structure of monolithic companies is comparatively easy, which can also be the benefit of monolithic companies. Buyer requests are parsed by means of DNS
and forwarded to the mall’s backend companies by means of Nginx
. Mall companies are deployed on cloud hosts. With a view to obtain better throughput and excessive availability, the service will typically deployed with a number of copies. This straightforward structure can carry excessive throughput if properly optimized.

For instance, a request for order particulars interface /order/element
is routed to the order module, which depends on the account module and the product module to compose the whole order particulars again to the person, and a number of modules in a single service typically share the database and cache.

The following part describes how one can shortly implement a mall monolithic service based mostly on go-zero
. Devs who’ve used go-zero
know that we offer an API
format file to explain the Restful API
, after which we are able to generate the corresponding code by goctl
with one command, we simply have to fill within the corresponding enterprise logic within the logic
information. The mall service comprises a number of modules, and with a view to make the modules impartial from one another, completely different modules are outlined by separate API
s, however all of the API
s are outlined for a similar service (mall-api)
.
Create person.api
, order.api
, product.api
and mall.api
within the api
listing, the place mall.api
is the aggregated api
file. Different api
information are imported by way of import
directives.
api
|-- mall.api
|-- order.api
|-- product.api
|-- person.api
mall.api
is outlined as follows, the place syntax = "v1"
signifies that that is the v1
syntax of zero-api
.
syntax = "v1"import "person.api"
import "order.api"
import "product.api"
- View person particulars
- Get all orders for a person
syntax = "v1"kind (
UserRequest
ID int64 `path:"id"`
UserReply
ID int64 `json:"id"`
Title string `json:"identify"`
Stability float64 `json:"stability"`
UserOrdersRequest
ID int64 `path:"id"`
UserOrdersReply
ID string `json:"id"`
State uint32 `json:"state"`
CreateAt string `json:"create_at"`
)service mall-api
@handler UserHandler
get /person/:id (UserRequest) returns (UserReply) @handler UserOrdersHandler
get /person/:id/orders (UserOrdersRequest) returns (UserOrdersReply)
- Get order particulars
- Generate orders
syntax = "v1"kind (
OrderRequest
ID string `path:"id"`
OrderReply
ID string `json:"id"`
State uint32 `json:"state"`
CreateAt string `json:"create_at"`
OrderCreateRequest
ProductID int64 `json:"product_id"`
OrderCreateReply
Code int `json:"code"`
)service mall-api
@handler OrderHandler
get /order/:id (OrderRequest) returns (OrderReply) @handler OrderCreateHandler
publish /order/create (OrderCreateRequest) returns (OrderCreateReply)
syntax = "v1"kind ProductRequest
ID int64 `path:"id"`
kind ProductReply
ID int64 `json:"id"`
Title string `json:"identify"`
Worth float64 `json:"worth"`
Depend int64 `json:"depend"`
service mall-api
@handler ProductHandler
get /product/:id (ProductRequest) returns (ProductReply)
With the API
already outlined, producing a service with the API
turns into quite simple, we use goctl
to generate the monolithic service code.
$ goctl api go -api api/mall.api -dir .
The generated code is structured as follows.
.
├── api
│ ├── mall.api
│ ├── order.api
│ ├── product.api
│ └── person.api
├── and many others
│ └── mall-api.yaml
├─ inner
│ ├── config
│ │ └── config.go
│ ├── handler
│ │ ├── ordercreatehandler.go
│ │ ├── orderhandler.go
│ │ ├── producthandler.go
│ │ ├── routes.go
│ │ ├── userhandler.go
│ │ └─ userordershandler.go
│ ├─ logic
│ │ ├─ ordercreatelogic.go
│ │ ├── orderlogic.go
│ │ ├── productlogic.go
│ │ ├── userlogic.go
│ │ └── userorderslogic.go
│ ├── svc
│ │ └── servicecontext.go
│ └── varieties
│ └── varieties.go
└── mall.go
Let’s clarify the generated information.
api
: holds theAPI
description fileand many others
: used to outline the challenge configuration, all configuration gadgets might be written inmall-api.yaml
inner/config
: the configuration definition of the serviceinner/handler
: the implementation of thehandler
akin to the routes outlined within theAPI
fileinner/logic
: used to place the enterprise logic corresponding to every route, the rationale for the excellence betweenhandler
andlogic
is to make the enterprise processing half as much less dependent as doable, to separateHTTP requests
from the logic processing code, and to facilitate the next splitting intoRPC service
inner/svc
: used to outline the dependencies of the enterprise logic processing, we are able to create the dependent sources within theprimary
operate and cross them tohandler
andlogic
by way ofServiceContext
inner/varieties
: defines theAPI
request and response knowledge constructionsmall.go
: the file the place theprimary
operate is situated, with the identical identify because theservice
within theAPI
definition, minus the-api
suffix
The generated service might be run with none modification: `
$ go run mall.go
Beginning server at 0.0.0.0:8888...
Subsequent, let’s implement the enterprise logic. The logic shall be easy for demonstration functions, not actual enterprise logic.
First, let’s implement the logic of getting all orders for customers. Since there isn’t any order-related info within the person module, we have to depend on the order module to question the orders of customers, so we add a dependency on OrderLogic
in UserOrdersLogic
.
kind UserOrdersLogic struct
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
orderLogic *OrderLogic
func NewUserOrdersLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserOrdersLogic
return &UserOrdersLogic
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
orderLogic: NewOrderLogic(ctx, svcCtx),
Implement a way in OrderLogic
to question all orders based mostly on person id
func (l *OrderLogic) ordersByUser(uid int64) ([]*varieties.OrderReply, error)
if uid == 123
// It ought to really be queried from database or cache
return []*varieties.OrderReply
ID: "236802838635",
State: 1,
CreateAt: "2022-5-12 22:59:59",
,
ID: "236802838636",
State: 1,
CreateAt: "2022-5-10 20:59:59",
,
, nil
return nil, nil
Name the ordersByUser
technique within the UserOrders
technique of UserOrdersLogic
.
func (l *UserOrdersLogic) UserOrders(req *varieties.UserOrdersRequest) (*varieties.UserOrdersReply, error)
orders, err := l.orderLogic.ordersByUser(req.ID)
if err ! = nil
return nil, err
return &varieties.UserOrdersReply
Orders: orders,
, nil
At this level we restart the mall-api
service and request all of the person’s orders within the browser.
http://localhost:8888/user/123/orders
The return result’s as follows, as we anticipated
"orders": [
"id": "236802838635",
"state": 1,
"create_at": "2022-5-12 22:59:59"
,
"id": "236802838636",
"state": 1,
"create_at": "2022-5-10 20:59:59"
]
Subsequent we’ll implement the logic for creating an order. To create an order we first have to see if the merchandise in inventory is sufficient, so we have to depend on the merchandise module within the order module.
kind OrderCreateLogic struct
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
productLogic *ProductLogic
productLogic *ProductLogic
func NewOrderCreateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *OrderCreateLogic
return &OrderCreateLogic
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
productLogic: NewProductLogic(ctx, svcCtx),
The logic for creating an order is as follows.
const (
success = 0
failure = -1
)func (l *OrderCreateLogic) OrderCreate(req *varieties.OrderCreateRequest) (*varieties.OrderCreateReply, error)
product, err := l.productLogic.productByID(req.ProductID)
if err ! = nil
return nil, err
if product.Depend > 0
return &varieties.OrderCreateReplyCode: success, nil
return &varieties.OrderCreateReplyCode: failure, nil
The logic of the dependent product module is as follows.
func (l *ProductLogic) Product(req *varieties.ProductRequest) (*varieties.ProductReply, error)
return l.productByID(req.ID)
func (l *ProductLogic) productByID(id int64) (*varieties.ProductReply, error)
return &varieties.ProductReply
ID: id,
Title: "apple watch 3",
Worth: 3333.33,
Depend: 99,
, nil
The above exhibits that utilizing go-zero
to develop a monolithic service may be very easy, which helps us to develop shortly. And we additionally separated modules, which additionally gives the potential for altering to microservices later.
The above instance exhibits that it is extremely easy to make use of go-zero
to develop monolithic companies. You solely have to outline the api
file, after which the goctl
software can robotically generate the challenge code. We solely have to fill within the enterprise logic code within the logic package deal. On this article, we simply demonstrated how one can shortly develop monolithic companies based mostly on go-zero
, which doesn’t contain databases. In actual fact, goctl
also can generate CRUD
and cache
code with one command.
And for various enterprise situations, customization may also be achieved by means of customizing templates. And customised templates might be shared throughout the staff by means of distant git
repositories, which might be very environment friendly for staff collaboration.
Wish to Join?Welcome to make use of go-zero and star to assist us!