惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
T
The Exploit Database - CXSecurity.com
V
Vulnerabilities – Threatpost
Know Your Adversary
Know Your Adversary
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
N
News and Events Feed by Topic
Spread Privacy
Spread Privacy
Application and Cybersecurity Blog
Application and Cybersecurity Blog
S
Secure Thoughts
G
GRAHAM CLULEY
Google Online Security Blog
Google Online Security Blog
Help Net Security
Help Net Security
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
O
OpenAI News
Google DeepMind News
Google DeepMind News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Security Archives - TechRepublic
Security Archives - TechRepublic
L
LINUX DO - 最新话题
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Stack Overflow Blog
Stack Overflow Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
L
Lohrmann on Cybersecurity
H
Hacker News: Front Page
W
WeLiveSecurity
P
Privacy International News Feed
Forbes - Security
Forbes - Security
月光博客
月光博客
PCI Perspectives
PCI Perspectives
T
Tailwind CSS Blog
N
News and Events Feed by Topic
T
Threat Research - Cisco Blogs
Engineering at Meta
Engineering at Meta
F
Full Disclosure
AI
AI
Hacker News - Newest:
Hacker News - Newest: "LLM"
Schneier on Security
Schneier on Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
D
Darknet – Hacking Tools, Hacker News & Cyber Security
V
Visual Studio Blog
The Hacker News
The Hacker News
博客园 - 叶小钗
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
博客园 - 司徒正美
T
The Blog of Author Tim Ferriss

博客园 - work hard work smart

使用 LangChain + Hugging Face 构建文本向量化服务 SQLAlchemy 使用详解 Python 中使用 Elasticsearch 的完整指南 Qdrant 向量数据库使用指南 OpenEvals 快速入门:LLM 评估指南 DeepEval 快速入门:LLM 应用评估指南 LangSmith 批量评估完全指南 Qwen-Agent 入门指南:快速构建智能体应用 LangSmith 集成实战:从追踪到评估的完整指南 RAG 中为什么需要 Rerank,以及如何使用 Rerank LangChain4j RAG 核心组件与组合方式 如何使用 Elasticsearch 进行全文检索和向量检索 MinerU Docker 部署指南 5 分钟上手:为 Cline 配置一个免费的 MCP 天气服务 Neo4j 图数据库安装与 Spring Boot 集成实战指南 LangFuse 实战指南:用 @observe 三行代码给 LLM 应用加上全链路追踪 Function Call 深度解析:让大模型从"嘴炮"到"实干"的技术革命 Spring AI 提示词模板实战:告别硬编码,实现提示词工程化管理 LangChain4j 实战指南:用 Java 轻松构建 AI 应用 Spring AI 对话短期记忆实战:让大模型拥有"记忆力" Spring AI 提示词工程实战:让大模型更懂你的意图 Spring AI ChatClient 深度解析:优雅构建大模型应用的利器 Spring AI Alibaba DashScopeChatModel 实战 Spring 中 SSE 流式输出的多种实现方式详解 OpenSandbox 实战指南:为 AI Agent 构建安全的代码执行沙箱 在本机启动 LangGraph 开发服务器:完整指南 DeepAgents中Backend的奥秘:让AI Agent拥有文件操作能力 为什么选择 Go 开发 Web 接口?从入门到实践 智能搜索DeepAgent笔记 RAG学习笔记2--系统查询流程 RAG学习笔记1--系统文件导入流程 百炼 WebSearch 快速入门指南 Python 连接 MongoDB 完整指南:从连接配置到增删改查实战 一行命令搞定 MongoDB 开发环境:Docker Compose 部署 + 可视化管理 使用 Attu 可视化管理 Milvus 向量数据库 在 Windows Docker 中快速安装 Milvus 2.5.6 minio使用 Spark 集群搭建 hadoop集群安装 Spring AI Alibaba 入门实战 Windows 安装 OpenClaw 实战指南 MyBatis 核心流程和原理 Idea中安装Claude code插件 Spark 编程 使用Matplotlib 绘制直方图 Flink安装部署 Flume安装 查找导致cpu过高的代码方法 JVisualVM监控远程Java进程 jmap jacoco多模块生成java单元测试报告实践 arthas 使用demo LockSupport Exchanger CyclicBarrier CountDownLatch 手把手教你用python开始第一个机器学习项目
初识 go-zero:一款让你写后端更规范、更高效的 Go 微服务框架
work hard work smart · 2026-06-21 · via 博客园 - work hard work smart

初识 go-zero:一款让你写后端更规范、更高效的 Go 微服务框架

前言

在 Go 语言的后端开发领域,提到 Web 框架,很多人第一个想到的是 Gin。Gin 轻量、简洁、性能好,非常适合快速搭建 API 服务。但当你从个人项目进入团队协作,或者从单服务走向微服务架构时,你会发现光有路由和中间件是不够的。

这时候你可能需要一套更完整、更规范、更工程化的东西。

go-zero 就是为此而生。


什么是 go-zero?

官网:https://go-zero.dev

go-zero 是一个集 Web 框架 + 微服务框架 + 代码生成工具于一体的 Go 工程化解决方案

它不像 Gin 那样只提供 HTTP 路由和中间件,而是给你一整套后端服务开发的规范和实践:

  • HTTP 和 RPC 服务框架
  • 配置文件管理
  • 超时控制、限流、熔断
  • 链路追踪
  • 日志和监控
  • 代码生成器 goctl
  • SQL 和缓存模型生成
  • DDD 风格的分层架构

它由中国开发者团队(好未来/晓教育)开源,已经在多家公司的生产环境大规模使用。


为什么要用 go-zero?

1. 一套规范,团队统一

go-zero 强制约定项目的目录结构和分层方式:

project/
├── user.api          # 接口定义(类似 API 合同)
├── user.go           # 程序入口
├── etc/              # 配置文件
└── internal/
    ├── config/       # 配置结构
    ├── handler/      # HTTP 请求处理
    ├── logic/        # 业务逻辑
    ├── model/        # 数据访问
    ├── svc/          # 服务依赖
    └── types/        # 请求/响应类型

新成员加入团队,不需要争论"service 放哪"、"dao 怎么命名"——所有人都按同一套方式组织代码。项目维护成本变低,review 变快。

2. 开箱即用的生产能力

开发一个后端服务,除了写业务代码,你还需要考虑:

  • 处理超时
  • 防止过载(限流)
  • 记录日志
  • 监控接口
  • 优雅关闭
  • 配置管理

Gin 把这些留给你自己解决,而 go-zero 内置了这些能力。一个 rest.MustNewServer 启动的服务,天然自带超时控制、限流和链路追踪。

3. 代码生成,少写重复代码

配合 goctl 工具,你可以从 .api 文件生成 handler、logic、types 的骨架代码,大幅减少重复的 CRUD 代码量。

4. 微服务支持

如果你需要从单体走向 RPC,go-zero 有内置的 zrpc 框架,与 go-zero/rest 共用一套配置、日志、链路追踪体系,迁移成本很低。


go-zero 和 Gin 到底有什么区别?

对比项 Gin go-zero
定位 Web HTTP 框架 微服务/API 工程框架
功能范围 路由 + 中间件 路由 + 中间件 + 配置 + 限流 + 熔断 + 链路追踪 + 日志 + 监控 + 代码生成
项目规范 不约束(自由组织) 强约束(分层约定)
代码生成 goctl 工具生成
数据访问 通常配 GORM 通常配 go-zero sqlx 或 GORM
中间件 Gin middleware go-zero middleware
服务治理 自己实现或接第三方 内置
微服务 需要自己组合其他框架 内置 zrpc
配置管理 内置 conf.MustLoad
学习门槛 中(有自己的一套约定)
适合场景 小中型项目 / 简单 API 工程化项目 / 微服务 / 团队协作
性能 略优 接近(框架层额外开销通常被业务耗时淹没)

性能话题

很多人关心 Gin 和 go-zero 谁更快。这个问题的正确答案是:看你的业务瓶颈在哪

  • 纯粹的路由转发,Gin 略快
  • 一旦你的接口需要查数据库(耗时 1~100ms)、调外部服务(耗时 10~500ms),框架层的微秒级差异可以忽略不计
  • go-zero 默认绑定的限流、日志、追踪等中间件会带来少量额外开销,但这是你写生产服务本来就应该加的

简单来说:如果你的接口只是个 "ok" 的返回,Gin 可以快一点;但真实业务里,性能瓶颈绝对不在框架上,而在你的 SQL、缓存和架构设计上。


一个用户增删改查的实现

前面说那么多,不如看代码。下面是用 go-zero 实现一个用户 CRUD 的完整例子。

使用的 ORM 框架

go-zero 官方推荐使用自己的 sqlx 包:

import "github.com/zeromicro/go-zero/core/stores/sqlx"

它不是一个完整的 ORM(对象关系映射),而是一个轻量 SQL 访问层,特点:

  • 提供连接池管理
  • 支持 MySQL、PostgreSQL、SQLite
  • 原生 SQL 写法,SQL 执行透明可控
  • 与 GORM 对比:
对比项 GORM go-zero sqlx
类型 全功能 ORM 轻量 SQL 访问层
查询方式 链式调用 手写 SQL
自动迁移 支持 不支持
学习曲线 需要记住框架 API 会 SQL 就能用
SQL 可见性 框架自动生成 全在代码里,可见可控

当然,go-zero 也可以配 GORM,但官方和社区更倾向于 sqlx。

环境准备

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

数据库表

CREATE TABLE IF NOT EXISTS users (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  email VARCHAR(200) NOT NULL,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

项目结构

demo_gozero/
├── user.go                    # 入口
├── user.api                   # API 定义(合同)
├── etc/
│   └── user-api.yaml          # 配置
├── sql/
│   └── users.sql              # 建表 SQL
└── internal/
    ├── config/
    │   └── config.go          # 配置结构
    ├── handler/
    │   ├── routes.go          # 路由注册
    │   ├── userhandler.go     # HTTP 处理器
    │   └── response.go        # 统一响应
    ├── logic/
    │   └── userlogic.go       # 业务逻辑
    ├── model/
    │   └── user.go            # 数据访问层(sqlx)
    ├── svc/
    │   └── servicecontext.go  # 服务依赖
    └── types/
        └── types.go           # 请求/响应类型

核心代码

入口

// user.go
package main

import (
    "flag"
    "fmt"
    "demo_gozero/internal/config"
    "demo_gozero/internal/handler"
    "demo_gozero/internal/svc"
    "github.com/zeromicro/go-zero/core/conf"
    "github.com/zeromicro/go-zero/rest"
)

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

func main() {
    flag.Parse()
    var c config.Config
    conf.MustLoad(*configFile, &c)
    server := rest.MustNewServer(c.RestConf)
    defer server.Stop()
    ctx := svc.NewServiceContext(c)
    handler.RegisterHandlers(server, ctx)
    fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
    server.Start()
}

配置

// internal/config/config.go
type Config struct {
    rest.RestConf
    Mysql struct {
       DataSource string
    }
}

对应的 yaml:

# etc/user-api.yaml
Name: user-api
Host: 0.0.0.0
Port: 8080
Mysql:
  DataSource: root:mypassword@tcp(127.0.0.1:23306)/my_user?charset=utf8mb4&parseTime=true&loc=Local

服务依赖

// internal/svc/servicecontext.go
type ServiceContext struct {
    Config    config.Config
    UserModel model.UserModel
}

func NewServiceContext(c config.Config) *ServiceContext {
    conn := sqlx.NewMysql(c.Mysql.DataSource)
    return &ServiceContext{
       Config:    c,
       UserModel: model.NewUserModel(conn),
    }
}

数据访问层(sqlx)

// internal/model/user.go
type UserModel interface {
    Insert(ctx context.Context, user *User) (sql.Result, error)
    FindOne(ctx context.Context, id int64) (*User, error)
    FindAll(ctx context.Context) ([]User, error)
    Update(ctx context.Context, user *User) error
    Delete(ctx context.Context, id int64) error
    Search(ctx context.Context, name string, page, limit int) ([]User, int64, error)
}

type defaultUserModel struct {
    conn sqlx.SqlConn
}

func (m *defaultUserModel) FindOne(ctx context.Context, id int64) (*User, error) {
    var user User
    err := m.conn.QueryRowCtx(ctx, &user, "select id, name, email, created_at, updated_at from users where id = ? limit 1", id)
    if errors.Is(err, sqlx.ErrNotFound) {
       return nil, ErrNotFound
    }
    return &user, err
}

func (m *defaultUserModel) FindAll(ctx context.Context) ([]User, error) {
    var users []User
    err := m.conn.QueryRowsCtx(ctx, &users, "select id, name, email, created_at, updated_at from users order by id desc")
    return users, err
}
// ... Insert, Update, Delete 类似

业务逻辑

// internal/logic/userlogic.go
func (l *UserLogic) GetUsers() ([]types.User, error) {
    users, err := l.svcCtx.UserModel.FindAll(l.ctx)
    if err != nil {
       return nil, err
    }
    return toTypeUsers(users), nil
}

func (l *UserLogic) CreateUser(req types.UserRequest) (*types.User, error) {
    result, err := l.svcCtx.UserModel.Insert(l.ctx, &model.User{Name: req.Name, Email: req.Email})
    if err != nil {
       return nil, err
    }
    id, _ := result.LastInsertId()
    return l.GetUserByID(id)
}

HTTP 处理器

// internal/handler/userhandler.go
func GetUsersHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
       l := logic.NewUserLogic(r.Context(), svcCtx)
       users, err := l.GetUsers()
       if err != nil {
          Error(w, http.StatusInternalServerError, "获取用户列表失败")
          return
       }
       OkWithData(w, "获取用户列表成功", users)
    }
}

路由注册

// internal/handler/routes.go
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
    server.AddRoutes([]rest.Route{
       {Method: http.MethodGet, Path: "/api/v1/users", Handler: GetUsersHandler(serverCtx)},
       {Method: http.MethodGet, Path: "/api/v1/users/:id", Handler: GetUserByIDHandler(serverCtx)},
       {Method: http.MethodPost, Path: "/api/v1/users", Handler: CreateUserHandler(serverCtx)},
       {Method: http.MethodPut, Path: "/api/v1/users/:id", Handler: UpdateUserHandler(serverCtx)},
       {Method: http.MethodDelete, Path: "/api/v1/users/:id", Handler: DeleteUserHandler(serverCtx)},
       {Method: http.MethodGet, Path: "/api/v1/users/search", Handler: SearchUsersHandler(serverCtx)},
    })
}

统一响应

所有接口返回相同格式:

{
  "code": 0,
  "message": "操作成功",
  "data": {}
}

错误时:

{
  "code": 400,
  "message": "无效的用户ID"
}

什么时候该选 go-zero?

我自己的建议:

场景 推荐
学习 Go 后端、个人 Demo 项目 Gin
简单 API 网关、微服务中的转发层 Gin
小团队(1-3人)的中型项目 go-zero
多人协作的长期项目 go-zero
从单体走向微服务的迁移项目 go-zero
需要规范化、代码 Review 友好的项目 go-zero
快速启动、不想学习框架约定 Gin

总结

  • Gin 的哲学是给你一把快刀,你想怎么切就怎么切
  • go-zero 的哲学是给你一套厨房,切菜、炒菜、洗碗、排烟都安排好了

没有绝对的好坏,只有适不适合。

如果你在做一个人维护的小服务,Gin 永远是好的选择。但如果你在一个团队里做后端开发,需要降维沟通成本、提升代码一致性、让新成员第二天就能跟上节奏——go-zero 值得一试