go-zero?rpc分布式微服務(wù)使用詳解
安裝go必要環(huán)境
下載go
https://go.dev/dl/ # inter版本 https://go.dev/dl/go1.25.5.windows-amd64.msi
配置GOROOT
配置代理

安裝goctl工具
go install github.com/zeromicro/go-zero/tools/goctl@latest goctl --version
出現(xiàn)下面的信息說(shuō)明go-zero安裝成功


創(chuàng)建第一個(gè)項(xiàng)目
初始化api項(xiàng)目
goctl api new user

查看生成的項(xiàng)目

下載依賴(lài)
切換到user目錄,下載依賴(lài)
cd user go mod tidy
結(jié)果
cd user PS E:\work\golang\demo\user> go mod tidy go: finding module for package github.com/zeromicro/go-zero/core/logx go: finding module for package github.com/zeromicro/go-zero/rest go: finding module for package github.com/zeromicro/go-zero/core/conf go: finding module for package github.com/zeromicro/go-zero/rest/httpx go: found github.com/zeromicro/go-zero/core/conf in github.com/zeromicro/go-zero v1.9.4 go: found github.com/zeromicro/go-zero/rest in github.com/zeromicro/go-zero v1.9.4 go: found github.com/zeromicro/go-zero/rest/httpx in github.com/zeromicro/go-zero v1.9.4 go: found github.com/zeromicro/go-zero/core/logx in github.com/zeromicro/go-zero v1.9.4 go: downloading github.com/stretchr/testify v1.11.1 go: downloading github.com/google/uuid v1.6.0 go: downloading k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 go: downloading github.com/golang-jwt/jwt/v4 v4.5.2 go: downloading gopkg.in/h2non/gock.v1 v1.1.2 go: downloading github.com/google/go-cmp v0.6.0 go: downloading google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 go: downloading github.com/kylelemons/godebug v1.1.0 go: downloading github.com/prometheus/procfs v0.15.1 go: downloading go.uber.org/goleak v1.3.0 go: downloading github.com/stretchr/objx v0.5.2 go: downloading github.com/davecgh/go-spew v1.1.1 go: downloading github.com/pmezard/go-difflib v1.0.0 go: downloading github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 go: downloading gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c go: downloading github.com/kr/pretty v0.3.1 go: downloading github.com/prashantv/gostub v1.1.0 go: downloading github.com/rogpeppe/go-internal v1.10.0 go: downloading github.com/kr/text v0.2.0
運(yùn)行user模塊
運(yùn)行啟動(dòng)user模塊
go run user.go Starting server at 0.0.0.0:8888...
生成文件詳細(xì)解釋

配置文件
- user/etc/user-api.yaml
Name: user-api # 服務(wù)名 Host: 0.0.0.0 # 主機(jī) Port: 8888 #端口
定義協(xié)議
- user/user.api
syntax = "v1" # 版本
# 請(qǐng)求 `type` 對(duì)于生成的Request 在`user/internal/types/types.go` 的 `Request`
type Request {
Name string `path:"name,options=you|me"`
}
# 響應(yīng) `type` 對(duì)于生成的Response 在`user/internal/types/types.go` 的 `Response`
type Response {
Message string `json:"message"`
}
# 方法, UserHandler在`user/internal/handler/userhandler.go`里
service user-api {
@handler UserHandler
get /from/:name (Request) returns (Response)
}
類(lèi)型type
- user/internal/types/types.go
package types
type Request struct {
Name string `path:"name,options=you|me"`
}
type Response struct {
Message string `json:"message"`
}
svc 上下文
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package svc
import (
"demo/user/internal/config"
)
type ServiceContext struct {
Config config.Config
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
}
}
邏輯logic
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package logic
import (
"context"
"demo/user/internal/svc"
"demo/user/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type UserLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserLogic {
return &UserLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *UserLogic) User(req *types.Request) (resp *types.Response, err error) {
// todo: add your logic here and delete this line
return &types.Response{
Message: "===========Hello World==========",
}, nil
}
路由
// Code generated by goctl. DO NOT EDIT.
// goctl 1.9.2
package handler
import (
"net/http"
"demo/user/internal/svc"
"github.com/zeromicro/go-zero/rest"
)
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodGet,
Path: "/from/:name",
Handler: UserHandler(serverCtx),
},
},
)
}
瀏覽器查看
http://127.0.0.1:8888/from/you

http://127.0.0.1:8888/from/wo

知識(shí)總結(jié)

熱加載
下載air
方便開(kāi)發(fā)
go install github.com/air-verse/air@latest air -v
運(yùn)行
不再運(yùn)行 go run user
air

Thunder Client 測(cè)試
vscode 安裝插件
go-zero項(xiàng)目解析










GRPC demo代碼生成
grpc服務(wù)是和http服務(wù)分開(kāi)的,不可以混為一談
例如:同為user模塊,既可以提供http服務(wù),也可以提供rpc服務(wù)
如果提供http服務(wù),命令行如下:
cd /user go run user.go
如果提供rpc服務(wù),相應(yīng)的配置,proto文件等需要生成。這里只講啟動(dòng)
cd /user/rpc go run user.go
以car項(xiàng)目為例
goctl rpc new car
創(chuàng)建過(guò)程
goctl rpc new car go: downloading google.golang.org/protobuf v1.36.11 go: downloading google.golang.org/grpc v1.78.0 go: downloading google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.0 go: downloading google.golang.org/protobuf v1.36.10 Done.
切換到car目錄下拉去依賴(lài)
go mod tidy
運(yùn)行
會(huì)報(bào)錯(cuò)
go run car

編輯該文件
internal/logic/pinglogic.go
商城微服務(wù) shop
規(guī)劃
| 服務(wù) | http端口 |
|---|---|
| user-api | 8881 |
| user-rpc | 8882 |
| order-api | 8883 |
| order-rpc | 8884 |
| product-api | 8885 |
| product-rpc | 8886 |
| cart-api | 8887 |
| cart-rpc | 8888 |
| product-api | 8887 |
| product-rpc | 8888 |
| gateway-api | 8889 |
| gateway-rpc | 8890 |
創(chuàng)建項(xiàng)目
mkdir -p shop/api cd shop
初始化init mod
go mod init finejade/shop-mall
定義 API 文件
網(wǎng)關(guān)服務(wù) api/gateway.api
// api/gateway.api
info (
title: "Shop Mall Gateway API"
desc: "API Gateway for the distributed shop mall system."
author: "Your Name"
email: "your.email@example.com"
version: "1.0.0"
)
// 1. 定義所有路由所需的具體請(qǐng)求和響應(yīng)結(jié)構(gòu)體
// 這些結(jié)構(gòu)體必須與各自微服務(wù) .api 文件中的定義保持一致!
type (
// --- 用戶(hù)服務(wù) (user.api) ---
UserRegisterReq {
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
}
UserRegisterResp {
Id int64 `json:"id"`
}
UserLoginReq {
Username string `json:"username"`
Password string `json:"password"`
}
UserLoginResp {
Token string `json:"token"`
}
GetUserInfoReq {
// 實(shí)際項(xiàng)目中,用戶(hù)ID通常從JWT Token解析,這里僅為演示
UserId int64 `json:"userId"`
}
UserInfo {
Id int64 `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
}
GetUserInfoResp {
User UserInfo `json:"user"`
}
// --- 商品服務(wù) (product.api) ---
GetProductListReq {
Page int `form:"page,default=1"`
PageSize int `form:"pageSize,default=10"`
}
ProductItem {
Id int64 `json:"id"`
Name string `json:"name"`
Price float64 `json:"price"`
ImageUrl string `json:"imageUrl"`
}
GetProductListResp {
List []ProductItem `json:"list"`
Total int64 `json:"total"`
}
GetProductDetailReq {
Id int64 `path:"id"`
}
GetProductDetailResp {
Product ProductItem `json:"product"`
}
// --- 購(gòu)物車(chē)服務(wù) (cart.api) ---
AddToCartReq {
UserId int64 `json:"userId"`
ProductId int64 `json:"productId"`
Quantity int `json:"quantity"`
}
GetCartListReq {
UserId int64 `json:"userId"`
}
CartItem {
ProductId int64 `json:"productId"`
ProductName string `json:"productName"`
Price float64 `json:"price"`
Quantity int `json:"quantity"`
}
GetCartListResp {
Items []CartItem `json:"items"`
}
UpdateCartItemReq {
UserId int64 `json:"userId"`
ProductId int64 `json:"productId"`
Quantity int `json:"quantity"`
}
DeleteCartItemReq {
UserId int64 `json:"userId"`
ProductId int64 `json:"productId"`
}
// --- 訂單服務(wù) (order.api) ---
CreateOrderReq {
UserId int64 `json:"userId"`
Address string `json:"address"`
}
CreateOrderResp {
OrderId int64 `json:"orderId"`
}
GetOrderListReq {
UserId int64 `json:"userId"`
}
OrderInfo {
Id int64 `json:"id"`
TotalPrice float64 `json:"totalPrice"`
Status string `json:"status"`
CreateTime string `json:"createTime"`
}
GetOrderListResp {
Orders []OrderInfo `json:"orders"`
}
GetOrderDetailReq {
Id int64 `path:"id"`
}
GetOrderDetailResp {
Order OrderInfo `json:"order"`
}
// --- 支付服務(wù) (payment.api) ---
CreatePaymentReq {
OrderId int64 `json:"orderId"`
Method string `json:"method"`
}
CreatePaymentResp {
PaymentUrl string `json:"paymentUrl"`
}
PaymentNotifyReq {
OutTradeNo string `json:"out_trade_no"`
TradeStatus string `json:"trade_status"`
}
PaymentNotifyResp {
Code string `json:"code"`
Msg string `json:"msg"`
}
// 2. 定義網(wǎng)關(guān)統(tǒng)一的、最終的對(duì)外響應(yīng)格式
GatewayResponse {
Code int `json:"code"` // 業(yè)務(wù)狀態(tài)碼, 0 代表成功
Msg string `json:"msg"` // 提示信息
Data interface{} `json:"data"` // 響應(yīng)數(shù)據(jù),這里可以是任意類(lèi)型
}
)
// 3. 在 service 塊中,為每個(gè)路由指定其具體的請(qǐng)求和響應(yīng)類(lèi)型
service gateway-api {
// --- 用戶(hù)服務(wù)路由 ---
@doc "用戶(hù)注冊(cè)"
@handler userRegisterHandler
post /api/user/register (UserRegisterReq) returns (GatewayResponse)
@doc "用戶(hù)登錄"
@handler userLoginHandler
post /api/user/login (UserLoginReq) returns (GatewayResponse)
@doc "獲取用戶(hù)信息"
@handler getUserInfoHandler
get /api/user/info (GetUserInfoReq) returns (GatewayResponse)
// --- 商品服務(wù)路由 ---
@doc "獲取商品列表"
@handler getProductListHandler
get /api/product/list (GetProductListReq) returns (GatewayResponse)
@doc "獲取商品詳情"
@handler getProductDetailHandler
get /api/product/:id (GetProductDetailReq) returns (GatewayResponse)
// --- 購(gòu)物車(chē)服務(wù)路由 ---
@doc "添加商品到購(gòu)物車(chē)"
@handler addToCartHandler
post /api/cart/add (AddToCartReq) returns (GatewayResponse)
@doc "獲取購(gòu)物車(chē)列表"
@handler getCartListHandler
get /api/cart/list (GetCartListReq) returns (GatewayResponse)
@doc "更新購(gòu)物車(chē)商品數(shù)量"
@handler updateCartItemHandler
post /api/cart/update (UpdateCartItemReq) returns (GatewayResponse)
@doc "刪除購(gòu)物車(chē)商品"
@handler deleteCartItemHandler
post /api/cart/delete (DeleteCartItemReq) returns (GatewayResponse)
// --- 訂單服務(wù)路由 ---
@doc "創(chuàng)建訂單"
@handler createOrderHandler
post /api/order/create (CreateOrderReq) returns (GatewayResponse)
@doc "獲取訂單列表"
@handler getOrderListHandler
get /api/order/list (GetOrderListReq) returns (GatewayResponse)
@doc "獲取訂單詳情"
@handler getOrderDetailHandler
get /api/order/:id (GetOrderDetailReq) returns (GatewayResponse)
// --- 支付服務(wù)路由 ---
@doc "創(chuàng)建支付"
@handler createPaymentHandler
post /api/payment/create (CreatePaymentReq) returns (GatewayResponse)
@doc "支付回調(diào)通知"
@handler paymentNotifyHandler
post /api/payment/notify (PaymentNotifyReq) returns (PaymentNotifyResp)
}
}
用戶(hù)服務(wù) api/user.api
info(
title: "User Service API"
desc: "Provides user registration, login, and profile management."
author: "Your Name"
email: "your.email@example.com"
version: "1.0.0"
)
type (
// --- 請(qǐng)求結(jié)構(gòu)體 ---
RegisterReq {
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
}
LoginReq {
Username string `json:"username"`
Password string `json:"password"`
}
GetUserInfoReq {
// 實(shí)際項(xiàng)目中,用戶(hù)ID通常從JWT Token中解析,這里僅作示例
UserId int64 `json:"userId"`
}
// --- 響應(yīng)結(jié)構(gòu)體 ---
RegisterResp {
Id int64 `json:"id"`
}
LoginResp {
Token string `json:"token"`
}
UserInfo {
Id int64 `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
}
GetUserInfoResp {
User UserInfo `json:"user"`
}
// 統(tǒng)一響應(yīng)
UserResponse {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
)
service user-api {
@handler registerHandler
post /user/register (RegisterReq) returns (UserResponse)
@handler loginHandler
post /user/login (LoginReq) returns (UserResponse)
@handler getUserInfoHandler
get /user/info (GetUserInfoReq) returns (UserResponse)
}
商品服務(wù) (api/product.api)
info(
title: "Product Service API"
desc: "Provides product listing and detail information."
author: "Your Name"
email: "your.email@example.com"
version: "1.0.0"
)
type (
// --- 請(qǐng)求結(jié)構(gòu)體 ---
GetProductListReq {
Page int `form:"page,default=1"`
PageSize int `form:"pageSize,default=10"`
}
GetProductDetailReq {
Id int64 `path:"id"`
}
// --- 響應(yīng)結(jié)構(gòu)體 ---
ProductItem {
Id int64 `json:"id"`
Name string `json:"name"`
Price float64 `json:"price"`
Description string `json:"description"`
Stock int `json:"stock"`
ImageUrl string `json:"imageUrl"`
}
GetProductListResp {
List []ProductItem `json:"list"`
Total int64 `json:"total"`
}
GetProductDetailResp {
Product ProductItem `json:"product"`
}
// 統(tǒng)一響應(yīng)
ProductResponse {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
)
service product-api {
@handler getProductListHandler
get /product/list (GetProductListReq) returns (ProductResponse)
@handler getProductDetailHandler
get /product/:id (GetProductDetailReq) returns (ProductResponse)
}
購(gòu)物車(chē)服務(wù) (cart.api)
info(
title: "Cart Service API"
desc: "Manages user shopping cart items."
author: "Your Name"
email: "your.email@example.com"
version: "1.0.0"
)
type (
// --- 請(qǐng)求結(jié)構(gòu)體 ---
AddToCartReq {
UserId int64 `json:"userId"`
ProductId int64 `json:"productId"`
Quantity int `json:"quantity"`
}
GetCartListReq {
UserId int64 `json:"userId"`
}
UpdateCartItemReq {
UserId int64 `json:"userId"`
ProductId int64 `json:"productId"`
Quantity int `json:"quantity"`
}
DeleteCartItemReq {
UserId int64 `json:"userId"`
ProductId int64 `json:"productId"`
}
// --- 響應(yīng)結(jié)構(gòu)體 ---
CartItem {
ProductId int64 `json:"productId"`
ProductName string `json:"productName"`
Price float64 `json:"price"`
Quantity int `json:"quantity"`
ImageUrl string `json:"imageUrl"`
}
GetCartListResp {
Items []CartItem `json:"items"`
}
// 統(tǒng)一響應(yīng)
CartResponse {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
)
service cart-api {
@handler addToCartHandler
post /cart/add (AddToCartReq) returns (CartResponse)
@handler getCartListHandler
get /cart/list (GetCartListReq) returns (CartResponse)
@handler updateCartItemHandler
post /cart/update (UpdateCartItemReq) returns (CartResponse)
@handler deleteCartItemHandler
post /cart/delete (DeleteCartItemReq) returns (CartResponse)
}
訂單服務(wù) (order.api)
info(
title: "Order Service API"
desc: "Manages the entire order lifecycle, from creation to fulfillment."
author: "Your Name"
email: "your.email@example.com"
version: "1.0.0"
)
type (
// --- 請(qǐng)求結(jié)構(gòu)體 ---
CreateOrderReq {
UserId int64 `json:"userId"`
// 實(shí)際項(xiàng)目中,地址信息會(huì)更復(fù)雜,這里簡(jiǎn)化
Address string `json:"address"`
}
GetOrderListReq {
UserId int64 `json:"userId"`
}
GetOrderDetailReq {
OrderId int64 `path:"id"`
}
// --- 響應(yīng)結(jié)構(gòu)體 ---
OrderItem {
ProductId int64 `json:"productId"`
ProductName string `json:"productName"`
Price float64 `json:"price"`
Quantity int `json:"quantity"`
}
OrderInfo {
Id int64 `json:"id"`
UserId int64 `json:"userId"`
TotalPrice float64 `json:"totalPrice"`
Status string `json:"status"` // e.g., "pending_payment", "paid", "shipped"
Items []OrderItem `json:"items"`
CreateTime string `json:"createTime"`
}
CreateOrderResp {
OrderId int64 `json:"orderId"`
}
GetOrderListResp {
Orders []OrderInfo `json:"orders"`
}
GetOrderDetailResp {
Order OrderInfo `json:"order"`
}
// 統(tǒng)一響應(yīng)
OrderResponse {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
)
service order-api {
@handler createOrderHandler
post /order/create (CreateOrderReq) returns (OrderResponse)
@handler getOrderListHandler
get /order/list (GetOrderListReq) returns (OrderResponse)
@handler getOrderDetailHandler
get /order/:id (GetOrderDetailReq) returns (OrderResponse)
}
支付服務(wù) (payment.api)
info(
title: "Payment Service API"
desc: "Handles payment processing and payment notifications."
author: "Your Name"
email: "your.email@example.com"
version: "1.0.0"
)
type (
// --- 請(qǐng)求結(jié)構(gòu)體 ---
CreatePaymentReq {
OrderId int64 `json:"orderId"`
// 支付方式, e.g., "alipay", "wechat"
Method string `json:"method"`
}
// 支付回調(diào)的請(qǐng)求體通常由第三方支付平臺(tái)定義,這里簡(jiǎn)化
PaymentNotifyReq {
OutTradeNo string `json:"out_trade_no"`
TradeStatus string `json:"trade_status"`
// ... 其他回調(diào)參數(shù)
}
// --- 響應(yīng)結(jié)構(gòu)體 ---
CreatePaymentResp {
// 支付鏈接或參數(shù),前端需要用它來(lái)喚起支付
PaymentUrl string `json:"paymentUrl"`
}
// 支付回調(diào)的響應(yīng)體也需要符合第三方平臺(tái)的要求,通常是 "success"
PaymentNotifyResp {
Code string `json:"code"`
Msg string `json:"msg"`
}
// 統(tǒng)一響應(yīng)
PaymentResponse {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
)
service payment-api {
@handler createPaymentHandler
post /payment/create (CreatePaymentReq) returns (PaymentResponse)
// 注意:支付回調(diào)接口通常是 POST,并且可能需要特殊的簽名驗(yàn)證
@handler paymentNotifyHandler
post /payment/notify (PaymentNotifyReq) returns (PaymentNotifyResp)
}
庫(kù)存 api/stock.api
info(
title: "Stock Service API"
desc: "Provides stock deduction and management for products."
author: "Your Name"
email: "your.email@example.com"
version: "1.0.0"
)
type (
// --- 請(qǐng)求結(jié)構(gòu)體 ---
DeductStockReq {
ProductId int64 `json:"productId"`
Quantity int `json:"quantity"`
OrderId string `json:"orderId"`
}
RollbackStockReq {
ProductId int64 `json:"productId"`
Quantity int `json:"quantity"`
OrderId string `json:"orderId"`
}
GetStockReq {
ProductId int64 `path:"productId"`
}
// --- 響應(yīng)結(jié)構(gòu)體 ---
StockResponse {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
GetStockData {
TotalStock int `json:"totalStock"`
AvailableStock int `json:"availableStock"`
}
)
service stock-api {
@doc "扣減庫(kù)存"
@handler deductStockHandler
post /stock/deduct (DeductStockReq) returns (StockResponse)
@doc "回滾庫(kù)存"
@handler rollbackStockHandler
post /stock/rollback (RollbackStockReq) returns (StockResponse)
@doc "獲取庫(kù)存信息"
@handler getStockHandler
get /stock/:productId (GetStockReq) returns (StockResponse)
}
生成各http服務(wù)代碼
# --- 網(wǎng)關(guān)服務(wù) --- # 網(wǎng)關(guān)通常是一個(gè) API Gateway 類(lèi)型的服務(wù) goctl api go -api api/gateway.api -dir gateway # --- 用戶(hù)服務(wù) --- goctl api go -api api/user.api -dir user # --- 商品服務(wù) --- goctl api go -api api/product.api -dir product # --- 訂單服務(wù) --- goctl api go -api api/order.api -dir order # --- 購(gòu)物車(chē)服務(wù) --- goctl api go -api api/cart.api -dir cart # --- 支付服務(wù) --- goctl api go -api api/payment.api -dir payment # --- 庫(kù)存服務(wù) --- # 庫(kù)存服務(wù)通常是一個(gè) RPC 服務(wù),用于內(nèi)部服務(wù)間調(diào)用 # 假設(shè)你已經(jīng)定義了 stock.proto # goctl rpc protoc api/stock.proto --go_out=stock --go-grpc_out=stock --zrpc_out=stock # 如果先用 API 風(fēng)格開(kāi)發(fā),命令如下: goctl api go -api api/stock.api -dir stock
ETCD
下載
https://github.com/etcd-io/etcd/tree/v3.6.7
運(yùn)行
啟動(dòng) Etcd: 解壓后,在本地啟動(dòng)一個(gè)單節(jié)點(diǎn)的 Etcd 服務(wù)。

圖形界面
下載
https://github.com/evildecay/etcdkeeper/releases
特點(diǎn)
etcdkeeper 目前最流行、最簡(jiǎn)單易用的 Etcd 可視化工具。它是一個(gè)單文件的二進(jìn)制應(yīng)用,無(wú)需任何依賴(lài),開(kāi)箱即用
特點(diǎn):
- 單文件部署:下載一個(gè)二進(jìn)制文件,直接運(yùn)行即可,非常方便。
- 界面簡(jiǎn)潔直觀:左側(cè)是目錄樹(shù),右側(cè)是鍵值對(duì),操作簡(jiǎn)單。
- 功能全面:支持增、刪、改、查,以及樹(shù)形結(jié)構(gòu)的展示。
- 跨平臺(tái):提供 Windows, macOS, Linux 版本。
運(yùn)行
解壓進(jìn)入目錄
etcdkeeper.exe -p 9999 2025/12/30 15:04:22 main.go:103: listening on 0.0.0.0:9999 2025/12/30 15:04:51 main.go:638: POST v3 connect success. 2025/12/30 15:04:51 main.go:701: GET v3 / 2025/12/30 15:04:53 main.go:701: GET v3 user.rpc/7587891840418209374
瀏覽器打開(kāi)
http://127.0.0.1:9999/etcdkeeper/

進(jìn)入左上角設(shè)置用戶(hù)名和密碼

RPC文件生成,配置
在每個(gè)服務(wù)的配置文件中添加 Etcd 配置
你需要修改每個(gè)服務(wù)的 etc/xxx-api.yaml 文件,告訴它們?nèi)绾芜B接到 Etcd。
以 user/etc/user-api.yaml 為例
Name: user-api Host: 0.0.0.0 Port: 8888 # ... 其他配置 ... # 新增 Etcd 配置 Etcd: Hosts: - 127.0.0.1:2379 Key: user.api # 這個(gè) Key 是服務(wù)在 Etcd 中的唯一標(biāo)識(shí)
服務(wù)間通信 (Inter-Service Communication)
這是微服務(wù)架構(gòu)的核心。我們將以 “訂單服務(wù)調(diào)用用戶(hù)服務(wù)獲取用戶(hù)信息” 為例,演示如何實(shí)現(xiàn)服務(wù)間調(diào)用。
將被調(diào)用方改造為 RPC 服務(wù) (以 user 服務(wù)為例)
HTTP API 服務(wù)主要用于對(duì)外(給前端或網(wǎng)關(guān))提供服務(wù)。服務(wù)間的高效通信應(yīng)該使用 RPC。
創(chuàng)建 user.proto: 在 api 目錄下創(chuàng)建一個(gè) user.proto 文件,定義 user 服務(wù)提供的 RPC 接口。
api/user.proto
syntax = "proto3";
package user;
option go_package = "./user";
message IdRequest {
int64 id = 1;
}
message UserResponse {
int64 id = 1;
string username = 2;
string email = 3;
}
service User {
rpc GetUserById(IdRequest) returns (UserResponse);
}
生成 RPC 代碼: 使用 goctl 生成 user 的 RPC 服務(wù)代碼
# 在項(xiàng)目根目錄下執(zhí)行 goctl rpc protoc api/user.proto --go_out=user/rpc --go-grpc_out=user/rpc --zrpc_out=user/rpc

整合 RPC 和 HTTP 服務(wù)
現(xiàn)在 user 目錄下既有 HTTP API 代碼,也有了 RPC 代碼。
你需要在 user.go 中同時(shí)啟動(dòng)這兩個(gè)服務(wù)。
** 1. 在 order 的配置文件中添加 user 服務(wù)的 RPC 配置:**
order/etc/order-api.yaml
Name: order-api
Host: 0.0.0.0
Port: 8889
# ... 其他配置 ...
# 新增要調(diào)用的 user 服務(wù)的 RPC 配置
UserRpc:
Etcd:
Hosts:
- 127.0.0.1:2379
Key: user.rpc # 這個(gè) Key 必須和 user 服務(wù)在 Etcd 中注冊(cè)的 Key 一致
** 2.新增:在調(diào)用的user服務(wù)的RPC配置 **
RpcClientConf:order/internal/config/config.go
package config
import (
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/zrpc"
)
type Config struct {
rest.RestConf
UserRpc zrpc.RpcClientConf // 新增這一行
}
3.在 order 的服務(wù)上下文中初始化 RPC 客戶(hù)端:
order/internal/svc/servicecontext.go
package svc
import (
"finejade/shop-mall/order/internal/config"
// 1. 導(dǎo)入生成的 user rpc 客戶(hù)端包
// 這個(gè)路徑是根據(jù)你的項(xiàng)目結(jié)構(gòu)和 user.proto 中的 go_package 生成的
"finejade/shop-mall/user/rpc/userclient"
"github.com/zeromicro/go-zero/zrpc"
)
type ServiceContext struct {
Config config.Config
// 2. 在這里聲明一個(gè) UserRpc 客戶(hù)端實(shí)例
// 它的類(lèi)型是 userclient.User
UserRpc userclient.User
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
// 3. 在這里初始化 UserRpc 客戶(hù)端
// zrpc.MustNewClient 會(huì)根據(jù)配置自動(dòng)從 Etcd 發(fā)現(xiàn)服務(wù)并創(chuàng)建連接
UserRpc: userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),
}
}
階段四:實(shí)現(xiàn)業(yè)務(wù)邏輯
- 現(xiàn)在,基礎(chǔ)設(shè)施已經(jīng)搭建完畢,你可以開(kāi)始填充每個(gè)服務(wù) internal/logic/ 目錄下的業(yè)務(wù)邏輯代碼了。例如:
- 在 user 服務(wù)中連接數(shù)據(jù)庫(kù),實(shí)現(xiàn)用戶(hù)的增刪改查。
- 在 product 服務(wù)中實(shí)現(xiàn)商品列表和詳情的查詢(xún)。
在 order 服務(wù)中,實(shí)現(xiàn)創(chuàng)建訂單的完整流程:
- 調(diào)用 user RPC 驗(yàn)證用戶(hù)信息。
- 調(diào)用 product RPC 獲取商品價(jià)格。
- 調(diào)用 stock RPC 預(yù)扣減庫(kù)存。
- 在本地?cái)?shù)據(jù)庫(kù)創(chuàng)建訂單記錄。
- 返回訂單 ID。

啟動(dòng)
以u(píng)ser為例,啟動(dòng)user-rpc服務(wù),如果需要,也可以啟動(dòng)user http服務(wù)
- 1、啟動(dòng)rpc服務(wù)
cd shop/user/rpc go run user.go Starting server at 0.0.0.0:8885...
- 2、啟動(dòng)http服務(wù)
cd shop/user go run user.go Starting server at 0.0.0.0:8885...
測(cè)試
訪問(wèn)order服務(wù),通過(guò)rpc查詢(xún)user服務(wù)數(shù)據(jù)
http://127.0.0.1:8881/order/list

改造product模塊為rpc
1. 生成proto3文件
syntax = "proto3";
package product;
option go_package = "./product";
message IdRequest {
int64 id = 1;
}
message ProductResponse {
int64 id = 1;
string name = 2;
string description = 3;
float price = 4;
}
service Product {
rpc GetProductById(IdRequest) returns (ProductResponse);
}
2. 命令生成product rpc
goctl rpc protoc api/product.proto --go_out=product/rpc --go-grpc_out=product/rpc --zrpc_out=product/rpc
3. order調(diào)用添加配置文件
order/etc/order-api.yaml
ProductRpc:
Etcd:
Hosts:
- 127.0.0.1:2379
Key: product.rpc # 這個(gè) Key 必須和 product 服務(wù)注冊(cè)的 Key 一致
4. 給order.api新增商品名稱(chēng)字段
api/order.api
并且重新生成 order服務(wù)模塊代碼 命令行:
goctl api go -api api/order.api -dir order
OrderInfo {
Id int64 `json:"id"`
UserId int64 `json:"userId"`
UserName string `json:"userName"` // <-- 新增字段,用于存放從 user-rpc 獲取的用戶(hù)名
//新增商品名稱(chēng)字段
ProductName string `json:"productName"` // 新增字段,用于存放從 product-rpc 獲取的商品名稱(chēng)
TotalPrice float64 `json:"totalPrice"`
Status string `json:"status"` // e.g., "pending_payment", "paid", "shipped"
Items []OrderItem `json:"items"`
CreateTime string `json:"createTime"`
}
5. config文件新增product rpc配置
路徑:order/internal/config/config.go
ProductRpc zrpc.RpcClientConf
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package config
import (
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/zrpc"
)
type Config struct {
rest.RestConf
// 新增:要調(diào)用的user服務(wù)的RPC配置
UserRpc zrpc.RpcClientConf
// 新增:要調(diào)用的product服務(wù)的RPC配置
ProductRpc zrpc.RpcClientConf
}
6. 聲明product rpc服務(wù)客戶(hù)端
order/internal/svc/servicecontext.go
package svc
import (
"finejade/shop-mall/order/internal/config"
"finejade/shop-mall/product/rpc/productclient"
// 1. 導(dǎo)入生成的 user rpc 客戶(hù)端包
// 這個(gè)路徑是根據(jù)你的項(xiàng)目結(jié)構(gòu)和 user.proto 中的 go_package 生成的
"finejade/shop-mall/user/rpc/userclient"
"github.com/zeromicro/go-zero/zrpc"
)
type ServiceContext struct {
Config config.Config
// 2. 在這里聲明一個(gè) UserRpc 客戶(hù)端實(shí)例
// 它的類(lèi)型是 userclient.User
UserRpc userclient.User
ProductRpc productclient.Product
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
// 3. 在這里初始化 UserRpc 客戶(hù)端
// zrpc.MustNewClient 會(huì)根據(jù)配置自動(dòng)從 Etcd 發(fā)現(xiàn)服務(wù)并創(chuàng)建連接
UserRpc: userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),
ProductRpc: productclient.NewProduct(zrpc.MustNewClient(c.ProductRpc)),
}
}
測(cè)試
http://127.0.0.1:8883/order/list

常用命令
部分命令可能因?yàn)榘姹締?wèn)題有變動(dòng)
| 命令 | 主要功能 | 實(shí)例 |
|---|---|---|
| goctl api new | 快速創(chuàng)建新項(xiàng)目骨架 | goctl api new user-api |
| goctl api go | 核心:根據(jù) .api 生成 Go 項(xiàng)目代碼 | goctl api go -api user.api -dir . |
| goctl api format | 格式化 .api 文件 | goctl api format api/user.api --dir api |
| goctl api validate | 校驗(yàn) .api 文件語(yǔ)法 | goctl api validate --api api/user.api |
| goctl api -o | 快速創(chuàng)建 *.api 文件,存在提示已存在,不存在則直接創(chuàng)建 | goctl api -o example.api |
| goctl api doc | 生成靜態(tài) HTML 文檔 | goctl api doc -api user.api -dir ./docs |
| goctl api swagger | 生成 Swagger (OpenAPI) JSON 文件 | goctl api swagger -api user.api -dir . |
| goctl api dart | 為 Flutter 生成 API 調(diào)用代碼 | goctl api dart -api user.api -dir ./dart-api |
goctl api format api/user.api --dir api
格式化前

格式化后(對(duì)齊了)

檢測(cè)api語(yǔ)法
goctl api validate --api api/user.api
錯(cuò)誤版本

正確版本

快速創(chuàng)建api
goctl api -o xxx.api
已存在的文件

不存在的文件


swagger文檔生成
goctl api swagger -api api/user.api -dir ./docs goctl api swagger -api api/order.api -dir ./docs

生成靜態(tài)html文檔
goctl api doc -api api/user.api -dir ./docs
為 TypeScript 生成 API 調(diào)用代碼
goctl api ts -api api/user.api -dir ./ts-api
swagger接口文檔使用
安裝
go install github.com/swaggo/swag/cmd/swag@latest
參數(shù)說(shuō)明
go-zero支持通過(guò)注解豐富Swagger文檔內(nèi)容,主要注解包括:
| 注解 | 作用 | 示例 |
|---|---|---|
| @summary | 接口簡(jiǎn)短描述 | @summary 用戶(hù)注冊(cè)接口 |
| @description | 接口詳細(xì)說(shuō)明 | @description 用于新用戶(hù)注冊(cè)賬號(hào),返回用戶(hù)ID |
| @tags | 接口分類(lèi)標(biāo)簽 | @tags 用戶(hù)管理 |
| @accept | 請(qǐng)求數(shù)據(jù)格式 | @accept application/json |
| @produce | 響應(yīng)數(shù)據(jù)格式 | @produce application/json |
| @param | 自定義請(qǐng)求參數(shù) | @param Authorization header string true “Bearer token” |
| @success | 成功響應(yīng)描述 | @success 200 {object} RegisterResponse “注冊(cè)成功” |
| @failure | 錯(cuò)誤響應(yīng)描述 | @failure 400 {object} ErrorResponse “參數(shù)錯(cuò)誤” |
帶注解的API示例
service user-api {
@handler RegisterHandler
@summary 用戶(hù)注冊(cè)接口
@description 用于新用戶(hù)注冊(cè)賬號(hào),用戶(hù)名需3-20個(gè)字符,密碼需6-32個(gè)字符
@tags 用戶(hù)管理
@accept application/json
@produce application/json
@param Authorization header string false "Bearer token"
@success 200 {object} RegisterResponse "注冊(cè)成功"
@failure 400 {object} ErrorResponse "參數(shù)錯(cuò)誤"
@failure 500 {object} ErrorResponse "服務(wù)器內(nèi)部錯(cuò)誤"
post /api/user/register (RegisterRequest) returns (RegisterResponse)
}
搭建swagger ui
下載
https://github.com/swagger-api/swagger-ui/releases # 或者csdn下載 https://download.csdn.net/download/xxpxxpoo8/92520157
部署
解壓后把文件復(fù)制到項(xiàng)目根目錄下swagger-ui文件夾里
修改接口地址
window.onload = function() {
//<editor-fold desc="Changeable Configuration Block">
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
window.ui = SwaggerUIBundle({
url: "http://localhost:8080/docs/user.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
//</editor-fold>
};
在根目錄下新建serve_swagger.go啟動(dòng)文件
// serve_swagger.go
package main
import (
"log"
"net/http"
)
func main() {
// 創(chuàng)建一個(gè)文件服務(wù)器,用于提供當(dāng)前目錄下的所有文件
fs := http.FileServer(http.Dir("."))
http.Handle("/", fs)
log.Println("Serving Swagger UI at http://localhost:8080/swagger-ui/dist/index.html")
log.Fatal(http.ListenAndServe(":8080", nil))
}
運(yùn)行
go run serve_swagger
打開(kāi)瀏覽器查看
http://localhost:8080/swagger-ui/dist/#/default/getUserInfoHandler

docker打包部署
切換到shop/user下運(yùn)行
go-zero 和goctl是獨(dú)立分開(kāi)的
如果 goctl命令未找到請(qǐng)安裝goctl
go install github.com/zeromicro/go-zero/tools/goctl@latest
1.構(gòu)建dockerfile文件
在根目錄下構(gòu)建dockerfile文件
goctl docker --go user/user.go --exe user
2.設(shè)置國(guó)內(nèi)鏡像加速器(大部分沒(méi)法用了)
如果國(guó)外鏡像超時(shí),可以使用國(guó)內(nèi)代理
sudo mkdir -p /etc/docker sudo nano /etc/docker/daemon.json
daemon.json
目前國(guó)內(nèi)我找到能用的鏡像就只有https://docker.1ms.run了
{
"registry-mirrors": [
"https://docker.1ms.run"
]
}
3.構(gòu)建鏡像
# 確保在 /root/shop 目錄 cd /root/shop # 重新構(gòu)建鏡像 docker build -t user-api:v1 -f ./user/Dockerfile .
FROM golang:alpine AS builder LABEL stage=gobuilder ENV CGO_ENABLED 0 RUN apk update --no-cache && apk add --no-cache tzdata WORKDIR /build # 在這里添加國(guó)內(nèi)代理 ENV GOPROXY=https://goproxy.cn,direct ADD go.mod . ADD go.sum . RUN go mod download COPY . . RUN go build -ldflags="-s -w" -o /app/user ./user FROM scratch COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai ENV TZ Asia/Shanghai WORKDIR /app COPY --from=builder /app/user /app/user COPY user/etc /app/etc CMD ["./user", "-f", "etc/user-api.yaml"]

4. 啟動(dòng)docker服務(wù)
docker run --rm -it -p 8881:8881 user:v1
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
完美解決golang go get私有倉(cāng)庫(kù)的問(wèn)題
這篇文章主要介紹了完美解決golang go get私有倉(cāng)庫(kù)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05
Golang+Vue輕松構(gòu)建Web應(yīng)用的方法步驟
本文主要介紹了Golang+Vue輕松構(gòu)建Web應(yīng)用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
go獲取協(xié)程(goroutine)號(hào)的實(shí)例
這篇文章主要介紹了go獲取協(xié)程(goroutine)號(hào)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
Golang中處理import自定義包出錯(cuò)問(wèn)題的解決辦法
最近開(kāi)始使用Go/GoLand在import自定義包時(shí)出現(xiàn)各種狀況,下面這篇文章主要給大家介紹了關(guān)于Golang中處理import自定義包出錯(cuò)問(wèn)題的解決辦法,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11
Golang中實(shí)現(xiàn)類(lèi)似類(lèi)與繼承的方法(示例代碼)
這篇文章主要介紹了Golang中實(shí)現(xiàn)類(lèi)似類(lèi)與繼承的方法,Go語(yǔ)言中通過(guò)方法接受者的類(lèi)型來(lái)決定方法的歸屬和繼承關(guān)系,本文通過(guò)示例代碼講解的非常詳細(xì),需要的朋友可以參考下2024-04-04

