Go-Zero基础入门2:快速构建API与RPC服务

纲要

  • 认识 go-zero 框架
    • 设计理念与核心特性
    • 环境依赖:GoRedisetcd
    • 核心组件:goctl 工具与核心库 github.com/zeromicro/go-zero
  • 快速安装与项目初始化
    • 安装 goctl
    • 获取核心依赖
  • 实践案例:构建 User 服务的 RPC 与 API
    • 整体流程:编写 .proto → 生成 RPC → 编写 .api → 生成 API → 联调
    • 使用 goctl 生成 RPC 服务
    • 使用 goctl 根据 .proto 生成代码
    • RPC 服务目录结构与设计意图
    • 编写业务逻辑与启动 RPC
    • 使用 goctl 生成 API 服务
    • API 目录结构与控制器
    • 在 API 中调用 RPC 服务
    • 联调验证
  • 总结

认识 go-zero 框架

go-zero 是一个集成了各种工程实践的 Web 和 RPC 框架,设计上充分吸收了微服务项目在实际开发中的痛点,并通过弹性设计、内置熔断、负载均衡等机制,让开发者可以更专注于业务逻辑本身。它的核心亮点可以概括为两点:

  • 声明式 API 定义:类似 Protocol Buffers.api 文件,用来描述 HTTP 接口的请求/响应结构,通过工具即可生成完整的 API 服务代码。
  • 微服务治理能力内建:无需手动引入第三方库,框架自带了自适应熔断、服务发现、负载均衡等功能,开箱即用。

除了这些设计理念,go-zero 还配备了一个强大的命令行工具 goctl,能够自动生成 RPC、API、模型等样板代码,大幅缩短从需求到上线的距离。

在开始使用之前,需要确保本地环境满足以下依赖:

  • Go(1.16+)
  • Redisgo-zero 在模型缓存中默认使用 Redis 作为缓存存储
  • etcdgo-zero 默认使用 etcd 作为服务注册与发现中心

go-zero 体系中的两个关键元素:

  • goctl:代码生成工具,可快速创建项目骨架。
  • github.com/zeromicro/go-zero:框架核心依赖库。

快速安装与项目初始化

安装 goctl

推荐直接下载预编译二进制文件,并放置到 $GOPATH/bin 目录下,以便全局使用。

# 使用 go install 安装(推荐)
$ go install github.com/zeromicro/go-zero/tools/goctl@latest 

安装完成后,执行 goctl --version 确认可用。

获取核心依赖

在项目根目录执行:

$ go mod init <your-module-name>
$ go get -u github.com/zeromicro/go-zero@latest 

这会将框架依赖写入 go.mod

实践案例:构建 User 服务的 RPC 与 API

本节将通过一个简单的 User 服务来演示如何用 go-zero 快速搭建 RPC 和 API,并实现两者间的调用。整体流程如下:

编写 user.proto

goctl 生成 RPC 代码

实现业务逻辑

启动 RPC 服务

编写 user.api

goctl 生成 API 代码

在 API 中集成 RPC 客户端

启动 API 服务

联调测试

使用 goctl 创建 RPC 服务骨架

首先创建一个空目录作为项目根目录,然后进入该目录,使用 goctl 快速生成一个名为 user 的 RPC 服务:

$ mkdir user-service && cd user-service 
$ goctl rpc new user 

执行后,目录中会出现一个基础的 RPC 项目结构。此时可以先查看一下,然后将其删除,因为我们通常会基于已有的 .proto 文件重新生成。

编写 .proto 并生成代码

在项目根目录下创建 rpc/user.proto,内容如下:

syntax = "proto3";
 
package user;
 
option go_package = "./user";
 
message GetUserReq {
  string id = 1;
}
 
message GetUserResp {
  string id = 1;
  string name = 2;
}
 
service User {
  rpc GetUser(GetUserReq) returns (GetUserResp);
}

然后使用 goctl 根据该 .proto 生成代码。假设当前位于 user-service 目录下,且 user.proto 放在 rpc/user.proto

$ cd rpc 
$ goctl rpc protoc user.proto --go_out=./types --go-grpc_out=./types --zrpc_out=.

其中:

  • --go_out--go-grpc_out 生成 protobuf 相关代码
  • --zrpc_out=. 生成 go-zero 的 RPC 服务框架代码,输出到当前目录

生成的目录结构如下:

rpc/
├── etc/
│   └── user.yaml            # 配置文件 
├── internal/
│   ├── config/
│   │   └── config.go        # 配置结构体 
│   ├── logic/
│   │   └── getuserlogic.go  # 业务逻辑 
│   ├── server/
│   │   └── userserver.go    # gRPC 服务实现 
│   └── svc/
│       └── servicecontext.go # 服务上下文 
├── types/
│   └── user/                # protobuf 生成的消息类型 
├── user.go                  # 入口文件 
├── user.proto 
└── userclient/
    └── user.go              # 客户端代码 

RPC 目录结构设计意图

  • etc:存放服务的配置文件(YAML),便于运维调整。
  • internal:服务内部实现,不对外暴露。
    • config:配置结构映射。
    • logic:核心业务逻辑,每个 RPC 方法对应一个 logic 文件。
    • server:实现 gRPC 接口,调用 logic 处理请求。
    • svc:服务上下文,集中管理依赖(如数据库连接、其他 RPC 客户端等)。
  • types:protobuf 生成的消息结构,供服务内外使用。
  • userclient:提供给外部调用的客户端封装,其他服务只需引用该包即可轻松调用本服务。

这种分层设计的核心思想是:“内核”逻辑集中在 internal 中,而可被外部引用的客户端、类型等则放在与 internal 同级的目录下,职责清晰,便于团队协作。

编写业务逻辑并启动 RPC

打开 internal/logic/getuserlogic.go,实现 GetUser 方法:

func (l *GetUserLogic) GetUser(in *user.GetUserReq) (*user.GetUserResp, error) {
    // 模拟业务逻辑:根据 ID 返回用户信息 
    return &user.GetUserResp{
        Id:   in.Id,
        Name: "Alice",
    }, nil 
}

然后进入 rpc 目录,启动服务:

$ go run user.go 

服务默认监听在配置文件中指定的地址(例如 0.0.0.0:8080),并且会向 etcd 注册。

使用 goctl 生成 API 服务

在项目根目录(user-service)下创建 api/user.api 文件:

syntax = "v1"
 
info (
    title:   "User API"
    desc:    "用户服务 HTTP 接口"
)
 
type (
    GetUserReq {
        Id string `json:"id"`
    }
    GetUserResp {
        Id   string `json:"id"`
        Name string `json:"name"`
    }
)
 
@server (
    prefix: /api/v1 
)
service user-api {
    @handler GetUser 
    get /user (GetUserReq) returns (GetUserResp)
}

.api 文件的语法类似 Protocol Buffers,但专为 HTTP 接口设计。其中 @server 定义路由前缀,@handler 标注处理器名称,get /user 则定义了具体的 HTTP 方法和路径。

生成 API 代码:

$ cd api 
$ goctl api go -api user.api -dir .

生成的目录结构如下:

api/
├── etc/
│   └── user-api.yaml 
├── internal/
│   ├── config/
│   ├── handler/
│   │   └── getuserhandler.go   # HTTP 处理器 
│   ├── logic/
│   │   └── getuserlogic.go     # 业务逻辑 
│   ├── svc/
│   │   └── servicecontext.go   # 服务上下文 
│   └── types/
│       └── types.go            # 请求/响应结构体 
├── user.api 
└── user.go                     # 入口文件 

在 API 中集成 RPC 客户端

为了让 API 服务能够调用 RPC 服务,需要先配置 RPC 客户端。编辑 api/etc/user-api.yaml,添加 RPC 服务发现配置:

Name: user-api 
Host: 0.0.0.0 
Port: 8888 
 
UserRpc:
  Etcd:
    Hosts:
      - 127.0.0.1:2379 
    Key: user.rpc 

然后在 internal/config/config.go 中增加对应的配置结构:

type Config struct {
    rest.RestConf 
    UserRpc zrpc.RpcClientConf 
}

internal/svc/servicecontext.go 中创建 RPC 客户端实例:

type ServiceContext struct {
    Config  config.Config 
    UserRpc userclient.User 
}
 
func NewServiceContext(c config.Config) *ServiceContext {
    return &ServiceContext{
        Config:  c,
        UserRpc: userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),
    }
}

最后在 internal/logic/getuserlogic.go 中实现业务逻辑,调用 RPC:

func (l *GetUserLogic) GetUser(req *types.GetUserReq) (resp *types.GetUserResp, err error) {
    rpcResp, err := l.svcCtx.UserRpc.GetUser(l.ctx, &user.GetUserReq{
        Id: req.Id,
    })
    if err != nil {
        return nil, err 
    }
    return &types.GetUserResp{
        Id:   rpcResp.Id,
        Name: rpcResp.Name,
    }, nil 
}

联调测试

确保 RPC 服务已在运行,然后启动 API 服务:

$ cd api 
$ go run user.go 

使用 curl 测试:

$ curl "http://127.0.0.1:8888/api/v1/user?id=1"
{"id":"1","name":"Alice"}

可以看到,API 服务成功调用了 RPC 服务并返回了用户信息。

总结

通过上述实践可以看到,go-zero 借助 goctl 工具,能够极快地生成 RPC 和 API 服务骨架,开发者只需填充业务逻辑即可完成微服务搭建。其目录结构的设计也充分体现了关注点分离和团队协作的最佳实践:

  • 外层为服务暴露的客户端和类型;
  • 内层internal)集中管理配置、上下文和业务逻辑;
  • 每个 RPC 方法独立为一个 logic 文件,职责单一。

这种风格不仅降低了初学者的上手门槛,也使得项目在规模扩大后依然能够保持良好的可维护性。后续还可以进一步探索 go-zero 的缓存、限流、队列等高级特性,但掌握 API 与 RPC 的协作模式,已经足以应对大多数微服务开发场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值