跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Go / Golang

go-zero 微服务架构入门与实践

go-zero 微服务框架的核心特性与实战应用。内容涵盖基于 .api 文件的接口定义与代码生成、goctl 脚手架使用、中间件机制(认证、日志、限流)、动态路由处理以及 RPC 服务集成。详细讲解了环境配置、项目结构、etcd 注册中心部署、Proto 协议编写与编译,以及 API 与 RPC 服务的交互流程,帮助开发者快速构建可维护、可扩展的微服务架构。

moshang发布于 2026/3/27更新于 2026/7/2356 浏览
go-zero 微服务架构入门与实践

go-zero 微服务架构入门与实践

在我最初看来,go-zero 最核心的价值体现在两点:

  1. 使用 .api 定义接口协议(Contract First)
  2. 使用 goctl 自动生成工程骨架,让开发者专注于业务逻辑

在使用中,我发现 go-zero 的核心并不止于脚手架,而是一整套围绕'可维护性、可扩展性'的工程化约束体系。

后来真正进入项目后,我才逐渐意识到:RPC(zrpc + etcd)才是 go-zero 支撑微服务架构的第二个关键支点。而中间件、熔断、限流、链路追踪,是第三个核心支点。

参考:go-zero 文档

配置环境

安装 goctl(go-zero 的脚手架)

go install github.com/zeromicro/go-zero/tools/goctl@latest

生成代码

方法一:一键生成

等环境配置完毕后,直接进入编辑器,在命令行中输入:

goctl api new firstdemo

骨架将自动搭建完毕。

方法二:手动创建 .api 文件

首先创建一个.api 文件:

syntax = "v1"
info (
    title: "gozero-demo"
    desc: "first api"
    author: "you"
    version: "1.0"
)
type(
    PingReq {
        name string `form:"name,optional"`
    }
    PingResp {
        message string `json:"message"`
    }
    CreateReq {
        title string `json:"title"`
        content string `json:"content"`
    }
    CreateResp {
        id int64 `json:"id"`
    }
)
service demo-api {
    @handler Ping get /ping (PingReq) returns (PingResp)
    @handler CreatePost post /posts (CreateReq) returns (CreateResp)
}

说明:

  • get/ping:GET 参数通常用 form:""(对应 query)
  • post /posts:POST JSON 用 json:""
  • @handler Xxx:生成的 handler/logic 名字,即对应的 router、控制器、业务层代码

执行命令:

goctl api go -api demo.api -dir .

生成的目录结构如下:

go_zero_project/
├── demo.api              # API 协议定义(接口契约,最核心)
├── demo-api.go           # 程序入口(main)
│   └── main()            # 启动 HTTP Server
├── etc/
│   └── demo-api.yaml     # 配置文件(端口 / DB / Redis / JWT 等)
├── internal/
│   ├── handler/          # HTTP 层(参数 → 逻辑)
│   │   ├── pinghandler.go
│   │   └── createposthandler.go
│   ├── logic/            # 业务逻辑层(核心代码写这里)
│   │   ├── pinglogic.go
│   │   └── createpostlogic.go
│   ├── types/            # 请求 / 响应结构体(由 .api 生成)
│   │   ├── ping.go
│   │   └── createpost.go
│   └── svc/
│       └── servicecontext.go # 依赖注入(DB / Redis / RPC Client)
└── go.mod                # Go Module 定义

热加载

下载 air:

go install github.com/air-verse/air@latest

运行:

air

作用:

  • 监听文件变化
  • 自动 go build
  • 杀掉旧进程 → 启动新进程

实现 GET/POST/PUT/DELETE

新建一个 first.api 的文件,依次粘贴以下四种不同类型的定义。

GET 查询

// 获取用户
type GetUserReq {
    id int64 `form:"id"`
}
type GetUserResp {
    id int64 `json:"id"`
    name string `json:"name"`
}
service demo-api {
    @handler GetUser get /user (GetUserReq) returns (GetUserResp)
}

POST 创建

// 创建用户
type CreateUserReq {
    name string `json:"name"`
    age int `json:"age"`
}
type CreateUserResp {
    id int64 `json:"id"`
}
service demo-api {
    @handler CreateUser post /user (CreateUserReq) returns (CreateUserResp)
}

PUT 更新

// 更新用户
type UpdateUserReq {
    id int64 `path:"id"`
    name string `json:"name"`
}
type UpdateUserResp {
    ok bool `json:"ok"`
}
service demo-api {
    @handler UpdateUser put /user/:id (UpdateUserReq) returns (UpdateUserResp)
}

DELETE 删除

// 删除用户
type DeleteUserReq {
    id int64 `path:"id"`
}
type DeleteUserResp {
    ok bool `json:"ok"`
}
service demo-api {
    @handler DeleteUser delete /user/:id (DeleteUserReq) returns (DeleteUserResp)
}

运行命令:

goctl api go -api firstdemo.api -dir .

之后即可得到基础的增删改查功能。

动态路由

只要仅操作一个资源的,都可以考虑用动态路由。

  1. 路由路径利用 :变量名:

    get /articles/:id
    

    :id 表示这里是一个占位符。

  2. 请求体里用 path:"变量名":

    type GetArticleReq {
        id int64 `path:"id"`
    }
    

    切记 path:"id" 必须和 :id 一模一样,否则解析不到值。

  3. method + handler 正确绑定:

    @handler GetArticle get /articles/:id (GetArticleReq) returns (GetArticleResp)
    

多个参数

GET /users/:userId/articles/:articleId
type GetUserArticleReq {
    userId int64 `path:"userId"`
    articleId int64 `path:"articleId"`
}

中间件

什么是中间件?

一条没有中间件的访问路径大致是这样:

HTTP Request ↓ handler ↓ logic ↓ response

但现实项目里,你经常要做些和业务无关、但每个接口都要做的事:

  1. 校验登录态 / Token
  2. 打日志
  3. 统一鉴权(验证权限)
  4. 限流(限制并发)
  5. 统计耗时

如果把这些都写进 logic 或 handler,结果是:每个接口重复写、业务逻辑被污染,后期根本维护不动。

挂载上中间件

中间件 = 在请求进入 handler 之前 / 返回响应之前,插一段统一逻辑。

HTTP Request ↓ Middleware(Auth / Log / RateLimit) ↓ handler ↓ logic ↓ response

在框架中的位置

internal/
├── middleware/ ← 中间件目录
│   └── authmiddleware.go
├── handler/ ← HTTP 参数解析
├── logic/ ← 业务逻辑
├── svc/
│   └── servicecontext.go ← 依赖注入(中间件从这拿资源)

记住:中间件 ≠ handler ≠ logic,它是作为一个独立层存在的。

中间件的样子

// Code scaffolded by goctl. Safe to edit.
package middleware
import "net/http"

type AuthMiddleware struct{}

func NewAuthMiddleware() *AuthMiddleware {
    return &AuthMiddleware{}
}

func (m *AuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        // TODO generate middleware implement function, delete after code implementation
        // Passthrough to next handler if need
        next(w, r)
    }
}

如何生成?

新建一个文件:auth.api

syntax = "v1"
type GetUserReq {
    id int64 `path:"id"`
}
type GetUserResp {
    id int64 `json:"id"`
}
@server (
    group: user
    middleware: Auth
)
service user-api {
    @handler GetUser get /users/:id (GetUserReq) returns (GetUserResp)
}

通过运行:

goctl api go -api auth.api -dir .

@doc 与 import

@doc 是什么?

@doc 是写在路由上的'接口说明元数据',用于生成文档/让接口更可读。

@doc "获取文章详情"
@handler GetArticle get /articles/:id (GetArticleReq) returns (GetArticleResp)

import 是什么?

当你的项目接口多了,一个 .api 文件会越来越大。import 的作用是把 api 文件拆分成多个小文件,再由一个入口 api 汇总。

布局方式:

api/
├── auth.api      # 入口(import 其它 api)
├── user.api      # 用户相关
└── types.api     # 公共 type(可选)

auth.api

syntax = "v1"
import "types.api"
import "user.api"

user.api

syntax = "v1"
@server(
    group: user
)
service user-api {
    @doc "获取用户详情"
    @handler GetUser get /users/:id (GetUserReq) returns (GetUserResp)
}

types.api

syntax = "v1"
type GetUserReq {
    id int64 `path:"id"`
}
type GetUserResp {
    id int64 `json:"id"`
    name string `json:"name"`
}

最后命令行一生成:

goctl api go -api auth.api -dir .

RPC 服务

首先,我们要先明确:RPC = 远程函数调用(像本地函数一样调用远程服务)。但注意!RPC 的核心不是'远程',而是:

  • 强接口约束(proto)
  • 高性能(HTTP/2 + protobuf)
  • 面向服务而不是面向资源

在 go-zero 里:

API 服务 ——(rpc client)——> RPC 服务 ——> 业务逻辑 / DB

在 rpc 与 go-zero 集合的项目中,往往少不了以下这四步:

  1. *.proto → 接口契约(定义有哪些方法、参数、返回值)
  2. goctl rpc new / protoc → 生成 RPC 服务骨架
  3. etc/*.yaml → RPC 监听端口、服务名
  4. internal/logic → 你真正写业务的地方

大家可以手动创建一个 user 的包,输入:

goctl rpc new

你将会得到:

user/
├── user.proto
├── user.go
├── etc/
│   └── user.yaml
├── internal/
│   ├── config/
│   ├── logic/
│   ├── server/
│   └── svc/
└── go.mod

这样一个骨架。此时你会看到,这样一份协议:

syntax = "proto3";
package user;
option go_package="./user";

message Request {
    string ping = 1;
}

message Response {
    string pong = 1;
}

service User {
    rpc Ping(Request) returns(Response);
}

与 user.go 中的启动函数。

package main
import (
    "flag"
    "fmt"
    "go_zero_project/gozero-rpc-demo/user/internal/config"
    "go_zero_project/gozero-rpc-demo/user/internal/server"
    "go_zero_project/gozero-rpc-demo/user/internal/svc"
    "go_zero_project/gozero-rpc-demo/user/user"
    "github.com/zeromicro/go-zero/core/conf"
    "github.com/zeromicro/go-zero/core/service"
    "github.com/zeromicro/go-zero/zrpc"
    "google.golang.org/grpc"
    "google.golang.org/grpc/reflection"
)

var configFile = flag.String("f", "etc/user.yaml", "the config file")

func main() {
    flag.Parse()
    var c config.Config
    conf.MustLoad(*configFile, &c)
    ctx := svc.NewServiceContext(c)
    s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
        user.RegisterUserServer(grpcServer, server.NewUserServer(ctx))
        if c.Mode == service.DevMode || c.Mode == service.TestMode {
            reflection.Register(grpcServer)
        }
    })
    defer s.Stop()
    fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
    s.Start()
}

在终端中输入 go mod tidy,更新拉取一下,run 一下,即可启动。

etcd

如果运行失败了,大概率是 etcd 尚未启动,这是新手最常见的问题之一。

什么是 etcd? etcd 你可以将其当成一个高可用的分布式 KV 存储(Key-Value),核心用途在微服务里是:

  • 服务发现:服务启动把自己的地址写进去(注册)
  • 配置中心/开关:把配置、feature flag 放进去
  • 分布式协调:租约、锁、选主....

如果你是第一次接触 etcd,可以先'功能上'把它理解为:一个专门给微服务用的「注册中心 / 配置中心」。

注意:

  • etcd ≠ Redis
  • etcd 具有强一致(Raft)
  • Redis 更偏缓存、高吞吐
一、下载

下载地址:https://github.com/etcd-io/etcd/releases

二、配置

把你含有以下两个文件的 cmd 路径,配置到全局 PATH 路径内:

  • etcd.exe
  • etcdctl.exe
三、运行

直接在 cmd 内,输入以下四个英文单词:

etcd

启动!

四、检测
netstat -ano | findstr :2379

看一看是否在监听!

此时,你在回去运行一下项目,自然就跑通了。

五、为什么要用这个?

看 etc 内的配置文件:

Name: user.rpc
ListenOn: 0.0.0.0:8080
Etcd:
  Hosts:
    - 127.0.0.1:2379
  Key: user.rpc

因为配置文件用到了 etcd。

调用 RPC 服务

初步调用

首先启动服务。之后在 apifox 中操作的,创建基于 grpc 的接口管理!(当然你换成其他也操作函数)然后把我的.proto 文件放置进去。在 user.User /Ping 接口上,点击调用。

{"pong":"hello"}

修改

插入这些,然后在 service User 里加一条:方法名:GetUser,请求:GetUserRequest,响应:GetUserResponse,并新增 2 个 message:

syntax = "proto3";
package user;
option go_package="./user";

message Request {
    string ping = 1;
}

message Response {
    string pong = 1;
}

message GetUserRequest {
    int64 id = 1;
}

message GetUserResponse {
    int64 id = 1;
    string name = 2;
}

service User {
    rpc Ping(Request) returns(Response);
    rpc GetUser(GetUserRequest) returns(GetUserResponse);
}

最关键的一步:

goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=.

同个这个,生成 rpc 代码框架。这里就是微服务中,被远程调用部分。也是 go-zero 中的,两个最重要的核心之一!而另一个就是 api,也就是对外!同时调用 rpc 的部分!

API

其实这个主要就两个步骤

一、生成 API 项目骨架

(一般,新启一个项目时用)

goctl api new userapi

二、写 .api 协议后生成代码

(更新项目时使用)

goctl api go -api userapi.api -dir .

其实 api 还有很多组件需要掌握:gorm、auth、jwt…但是这些其实都与 gin 框架大差不差。

这次就先记录到这里,如果想要了解更多、更详细的,可以直接到官网了解,文档写的还是非常简洁通透的:go-zero 文档

目录

  1. go-zero 微服务架构入门与实践
  2. 配置环境
  3. 生成代码
  4. 方法一:一键生成
  5. 方法二:手动创建 .api 文件
  6. 热加载
  7. 实现 GET/POST/PUT/DELETE
  8. GET 查询
  9. POST 创建
  10. PUT 更新
  11. DELETE 删除
  12. 动态路由
  13. 多个参数
  14. 中间件
  15. 什么是中间件?
  16. 挂载上中间件
  17. 在框架中的位置
  18. 中间件的样子
  19. 如何生成?
  20. @doc 与 import
  21. @doc 是什么?
  22. import 是什么?
  23. RPC 服务
  24. etcd
  25. 一、下载
  26. 二、配置
  27. 三、运行
  28. 四、检测
  29. 五、为什么要用这个?
  30. 调用 RPC 服务
  31. 初步调用
  32. 修改
  33. API
  34. 一、生成 API 项目骨架
  35. 二、写 .api 协议后生成代码
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Docker 安装部署全流程使用指南(Linux 通用版)
  • Rust 内联汇编:原理与实战
  • 命令行大模型上下文协议 MCPHost 工具使用指南
  • OpenClaw 多智能体路由实战:飞书多机器人配置
  • Python 发展前景与零基础入门学习路径
  • C++ 默认成员函数:构造、拷贝、析构与赋值
  • Android 音视频全栈开发学习路线与核心笔记整理
  • 编程基础概念:逻辑(Logic)详解
  • Flutter 混合开发技术选型与 PlatformView 实践指南
  • STM32 单片机充电桩安全监测系统
  • 即时通讯系统核心模块:从传输到存储的全链路设计
  • 为什么顶级团队开始重押 Harness Engineering?AI Agent 时代的底层答案来了
  • CSS 命名规范实战:BEM 模式与通用技巧
  • Python 技术副业指南:爬虫、接口与数据分析实战
  • browser-use:让 AI Agent 真正会用浏览器
  • Python 副业开发指南:数据分析、爬虫与量化交易实战
  • DeepSeek 各版本说明与优缺点分析
  • 8 卡 RTX 5090 服务器 llama.cpp 完整安装及性能调优
  • 基于 Docker 部署 Nginx 并实现公网远程访问
  • 大香蕉 (Banana Pro) 企业级落地白皮书:如何用 0.18 元打破 AIGC 的“商业不可能三角”?

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online