Skip to main content

go-zero v1.9.0

欢迎使用 go-zero v1.9.0!本次发布带来了强大的新功能、重要修复和性能改进,进一步提升您的微服务开发体验。

🆕 新功能

1. 日志数据脱敏(logx)

增强敏感数据日志安全性

新特性: 通过在数据类型上实现 MaskSensitive() any 方法,支持日志输出敏感数据脱敏。

快速开始:

package main

import "github.com/zeromicro/go-zero/core/logx"

// 定义包含敏感数据的结构体
type UserInfo struct {
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
}

// 实现 MaskSensitive 方法控制日志输出内容
func (u UserInfo) MaskSensitive() any {
return UserInfo{
Username: u.Username,
Password: "***", // 脱敏密码
Email: maskEmail(u.Email), // 部分脱敏邮箱
}
}

func maskEmail(email string) string {
parts := strings.Split(email, "@")
if len(parts) != 2 {
return "***"
}
return parts[0][:1] + "***@" + parts[1]
}

func main() {
user := UserInfo{
Username: "john",
Password: "secret123",
Email: "john@example.com",
}

// 自动使用 MaskSensitive() 方法
logx.Infow("User login", logx.Field("user", user))
// 输出: {"user":{"username":"john","password":"***","email":"j***@example.com"}}
}

2. sqlx 字段标签跳过逻辑

增强数据库字段处理,支持跳过标签

新特性: 支持使用 - 字段标签,在数据库操作时跳过对应字段。

快速开始:

type User struct {
ID int64 `db:"id"`
Name string `db:"name"`
Password string `db:"-"` // 此字段将被跳过
Internal string `db:"-"` // 此字段将被跳过
Email string `db:"email"`
}

// 查询用法 - 跳过字段自动忽略
var user User
err := sqlx.QueryRow(&user, "SELECT id, name, email FROM users WHERE id = ?", 1)

3. MongoDB 驱动升级至 v2

现代化 MongoDB 集成,性能提升

新特性: 升级至 mongo-driver v2,v1 已迁移至 zero-contrib 保持兼容。

迁移指南:

// 旧用法(v1 - 现已在 zero-contrib)
import "github.com/zeromicro/zero-contrib/stores/mongo"

// 新用法(v2 - 内置)
import "github.com/zeromicro/go-zero/core/stores/mongo"

func main() {
// 新 v2 API,性能提升
client := mongo.MustNewModel("mongodb://localhost:27017", "mydb", "users")

// 查询能力增强
var users []User
err := client.Find(context.Background(), &users, bson.M{"status": "active"})
}

4. 泛型 TypedSet,性能提升 2 倍

高性能泛型集合实现

新特性: 泛型 TypedSet,编译期安全,性能提升 2 倍。

快速开始:

import "github.com/zeromicro/go-zero/core/collection"

func main() {
// 创建字符串类型集合
stringSet := collection.NewTypedSet[string]()

// 添加元素
stringSet.Add("user1", "user2", "user3")

// 判断成员是否存在(性能提升 2 倍)
if stringSet.Contains("user1") {
fmt.Println("User found!")
}

// 整型集合用法
intSet := collection.NewTypedSet[int]()
intSet.Add(1, 2, 3)

// 集合操作
union := stringSet.Union(otherStringSet)
intersection := stringSet.Intersect(otherStringSet)
}

5. 网关自定义中间件(洋葱模型)

灵活的 API 网关中间件架构

新特性: 支持 API 网关自定义中间件,采用洋葱模型架构。

快速开始:

import "github.com/zeromicro/go-zero/gateway"

// 定义自定义中间件
func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 认证逻辑
token := r.Header.Get("Authorization")
if !validateToken(token) {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next(w, r)
}
}

func rateLimitMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 限流逻辑
if !checkRateLimit(r.RemoteAddr) {
http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)
return
}
next(w, r)
}
}

// 配置网关中间件栈
func main() {
gw := gateway.MustNewServer(gateway.GatewayConf{
Name: "api-gateway",
Port: 8080,
Upstreams: []gateway.Upstream{
{
Name: "user-service",
Mapping: "/api/users",
Target: "http://localhost:8081",
},
},
// 中间件栈(洋葱模型,从外到内)
Middlewares: []gateway.Middleware{
rateLimitMiddleware, // 外层
authMiddleware, // 内层
},
})

gw.Start()
}

6. Redis 消费者组

高级 Redis 流处理,支持消费者组

新特性: 原生支持 Redis 消费者组,实现可扩展流处理。

快速开始:

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

func main() {
rds := redis.MustNewRedis(redis.RedisConf{
Host: "localhost:6379",
})

// 创建消费者组
err := rds.XGroupCreate("events", "processors", "0", true)
if err != nil {
log.Fatal(err)
}

// 消费者函数
go func() {
for {
// 从消费者组读取
streams, err := rds.XReadGroup(&redis.XReadGroupArgs{
Group: "processors",
Consumer: "worker-1",
Streams: []string{"events", ">"},
Count: 10,
Block: time.Second * 5,
})

if err != nil {
log.Printf("Error reading: %v", err)
continue
}

// 处理消息
for _, stream := range streams {
for _, message := range stream.Messages {
processMessage(message)
// 消息确认
rds.XAck("events", "processors", message.ID)
}
}
}
}()
}

func processMessage(msg redis.XMessage) {
fmt.Printf("Processing message %s: %v\n", msg.ID, msg.Values)
}

7. 网关请求解析增强

提升未知字段处理灵活性

新特性: 网关在请求解析时自动忽略未知字段,提升 API 兼容性。

优势:

  • 向后兼容:旧客户端可携带废弃字段
  • 向前兼容:新客户端可安全携带新增字段
  • 优雅降级:服务在结构不匹配时可继续工作

示例:

// 服务端期望结构
type UserRequest struct {
Name string `json:"name"`
Email string `json:"email"`
}

// 客户端发送如下(多余字段将被忽略,不会报错)
{
"name": "John Doe",
"email": "john@example.com",
"deprecated_field": "old_value", // 优雅忽略
"future_field": "new_value" // 优雅忽略
}

8. 网关 gRPC 元数据转发

增强 gRPC 元数据转发到 HTTP 响应头

新特性: 网关自动将后端服务的 gRPC 元数据(headers 和 trailers)转发到 HTTP 响应头。

优势:

  • 完整元数据传递:所有 gRPC 头和尾部字段转发到 HTTP 客户端
  • 链路追踪支持:Trace ID 与调试信息可完整流转
  • 自定义头支持:后端可设定自定义头部直接到前端
  • 无缝集成:兼容现有网关配置

快速开始:

// 后端 gRPC 服务设置元数据
func (s *Service) SomeMethod(ctx context.Context, req *pb.Request) (*pb.Response, error) {
// 设置将被转发到 HTTP 响应的 header
err := grpc.SendHeader(ctx, metadata.Pairs(
"X-Custom-Header", "custom-value",
"X-Trace-ID", "trace-12345",
))
if err != nil {
return nil, err
}

// 设置将被转发的 trailer
grpc.SetTrailer(ctx, metadata.Pairs(
"X-Server-Info", "grpc-backend-v1",
"X-Processing-Time", "150ms",
))

return &pb.Response{}, nil
}

// 前端 HTTP 客户端将收到这些响应头:
// X-Custom-Header: custom-value
// X-Trace-ID: trace-12345
// X-Server-Info: grpc-backend-v1
// X-Processing-Time: 150ms

🐛 Bug 修复

1. ETCD 自动注册修复

解决服务发现可靠性问题

修复问题: 服务在 ETCD key 丢失时无法自动重新注册。

影响: 服务发现更可靠,实现自动恢复。

前后对比:

// 之前:需要手动重新注册
// 现在:自动恢复
config := etcd.EtcdConf{
Hosts: []string{"localhost:2379"},
Key: "user.rpc",
// 自动恢复现已可靠
}

2. SSE 超时配置

修复 Server-Sent Events 超时处理

修复问题: SSE 连接受 http.Server 的 WriteTimeout 影响,导致提前断开。

解决方案: SSE 独立处理超时,不再受服务器写超时影响。

// SSE 现在可正确处理超时
server := &http.Server{
WriteTimeout: 10 * time.Second, // 不影响 SSE
}

// SSE 连接有独立超时处理
http.HandleFunc("/events", func(w http.ResponseWriter, r *http.Request) {
// SSE 流不受服务器 WriteTimeout 限制
sse.StreamEvents(w, r, eventSource)
})

3. 环境变量解析修复

修复环境变量配置加载问题

修复问题: 加载类型为 time.Duration 的环境变量解析异常。

示例修复:

type Config struct {
Timeout time.Duration `json:",env=TIMEOUT"` // 现已正常工作
}

4. 大请求内存优化

优化详细请求日志内存占用

修复问题: 当日志 verbose 设为 true 时,日志记录 POST 请求体内容时内存消耗过大。

影响: 大请求体应用内存显著降低。


5. JSON 序列化 HTML 转义修复

修复 httpx 响应中的 HTML 转义问题

修复问题: JSON 序列化时错误的 HTML 转义导致响应格式异常。

修复前:

{"message": "Hello \\u003cworld\\u003e"}  // 错误转义

修复后:

{"message": "Hello <world>"}  // 正确输出

6. 并发资源访问修复

修复 ImmutableResource 并发访问竞态问题

修复问题: 并发访问 ImmutableResource 可能导致结果为空。

影响: 高并发场景下线程安全和可靠性提升。

⚡ 性能提升

字段日志优化

结构化字段处理日志性能提升。

优化点: 更快的日志处理,更少内存分配。

用法:

// 字段日志性能优化
logx.Infow("User action",
logx.Field("user_id", userID),
logx.Field("action", "login"),
logx.Field("timestamp", time.Now()),
)

🎯 迁移指南

从 v1.8.5 升级至 v1.9.0

  1. 更新依赖:
go get github.com/zeromicro/go-zero@v1.9.0
  1. MongoDB 驱动:

    • 如使用 MongoDB v1,请将导入路径更新为 zero-contrib
    • 推荐迁移至 v2,性能更优
  2. 消费者组:

    • 更新 Redis 流处理,使用新的消费者组 API

🙏 新增贡献者

欢迎首次贡献的优秀开发者:

📚 相关资源

🔗 链接


祝你使用 go-zero v1.9.0 编码愉快! 🎉