go-zero v1.9.0 ๐
Welcome to go-zero v1.9.0! This release brings powerful new features, important fixes, and performance improvements to enhance your microservices development experience.
๐ New Features
1. Data Masking in Logging (logx)
Enhanced security for sensitive data logging
What's New: Support for masking sensitive data in log output by implementing the MaskSensitive() any
method on data types.
Quick Start:
package main
import "github.com/zeromicro/go-zero/core/logx"
// Define a struct with sensitive data
type UserInfo struct {
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
}
// Implement MaskSensitive method to control what gets logged
func (u UserInfo) MaskSensitive() any {
return UserInfo{
Username: u.Username,
Password: "***", // Mask the password
Email: maskEmail(u.Email), // Partially mask 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",
}
// This will automatically use MaskSensitive() method
logx.Infow("User login", logx.Field("user", user))
// Output: {"user":{"username":"john","password":"***","email":"j***@example.com"}}
}
2. Field Tag Skip Logic in sqlx
Improved database field handling with skip tags
What's New: Support for -
field tag to skip fields during database operations.
Quick Start:
type User struct {
ID int64 `db:"id"`
Name string `db:"name"`
Password string `db:"-"` // This field will be skipped
Internal string `db:"-"` // This field will be skipped
Email string `db:"email"`
}
// Usage in queries - skipped fields are automatically ignored
var user User
err := sqlx.QueryRow(&user, "SELECT id, name, email FROM users WHERE id = ?", 1)
3. MongoDB Driver v2 Upgrade
Modern MongoDB integration with improved performance
What's New: Upgraded to mongo-driver v2 with v1 moved to zero-contrib for backward compatibility.
Migration Guide:
// Old way (v1 - now in zero-contrib)
import "github.com/zeromicro/zero-contrib/stores/mongo"
// New way (v2 - built-in)
import "github.com/zeromicro/go-zero/core/stores/mongo"
func main() {
// New v2 API with improved performance
client := mongo.MustNewModel("mongodb://localhost:27017", "mydb", "users")
// Enhanced query capabilities
var users []User
err := client.Find(context.Background(), &users, bson.M{"status": "active"})
}
4. Generic TypedSet with 2x Performance
High-performance generic set implementation
What's New: Generic TypedSet with compile-time safety and 2x performance improvement.
Quick Start:
import "github.com/zeromicro/go-zero/core/collection"
func main() {
// Create a typed set for strings
stringSet := collection.NewTypedSet[string]()
// Add items
stringSet.Add("user1", "user2", "user3")
// Check membership (2x faster than previous implementation)
if stringSet.Contains("user1") {
fmt.Println("User found!")
}
// Work with integers
intSet := collection.NewTypedSet[int]()
intSet.Add(1, 2, 3)
// Set operations
union := stringSet.Union(otherStringSet)
intersection := stringSet.Intersect(otherStringSet)
}
5. Gateway Custom Middleware (Onion Model)
Flexible middleware architecture for API gateways
What's New: Support for custom middleware with onion model architecture in API gateways.
Quick Start:
import "github.com/zeromicro/go-zero/gateway"
// Define custom middleware
func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Authentication logic
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) {
// Rate limiting logic
if !checkRateLimit(r.RemoteAddr) {
http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)
return
}
next(w, r)
}
}
// Configure gateway with middleware stack
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",
},
},
// Middleware stack (onion model - outer to inner)
Middlewares: []gateway.Middleware{
rateLimitMiddleware, // Outer layer
authMiddleware, // Inner layer
},
})
gw.Start()
}
6. Redis Consumer Groups
Advanced Redis stream processing with consumer groups
What's New: Native support for Redis consumer groups for scalable stream processing.
Quick Start:
import "github.com/zeromicro/go-zero/core/stores/redis"
func main() {
rds := redis.MustNewRedis(redis.RedisConf{
Host: "localhost:6379",
})
// Create consumer group
err := rds.XGroupCreate("events", "processors", "0", true)
if err != nil {
log.Fatal(err)
}
// Consumer function
go func() {
for {
// Read from consumer group
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
}
// Process messages
for _, stream := range streams {
for _, message := range stream.Messages {
processMessage(message)
// Acknowledge message
rds.XAck("events", "processors", message.ID)
}
}
}
}()
}
func processMessage(msg redis.XMessage) {
fmt.Printf("Processing message %s: %v\n", msg.ID, msg.Values)
}
7. Gateway Request Parsing Enhancement
Improved flexibility with unknown field handling
What's New: Gateway now ignores unknown fields in request parsing, improving API compatibility.
Benefits:
- Backward Compatibility: Older clients can send requests with deprecated fields
- Forward Compatibility: Newer clients can send additional fields safely
- Graceful Degradation: Services continue working despite schema mismatches
Example:
// Service expects this structure
type UserRequest struct {
Name string `json:"name"`
Email string `json:"email"`
}
// Client sends this (extra fields are now ignored, not rejected)
{
"name": "John Doe",
"email": "john@example.com",
"deprecated_field": "old_value", // Ignored gracefully
"future_field": "new_value" // Ignored gracefully
}
8. Gateway gRPC Metadata Forwarding
Enhanced gRPC metadata forwarding to HTTP headers in gateway
What's New: Gateway now automatically forwards gRPC metadata (headers and trailers) from backend services to HTTP response headers.
Benefits:
- Full Metadata Propagation: All gRPC headers and trailers are forwarded to HTTP clients
- Tracing Support: Trace IDs and debugging information flow through the gateway
- Custom Headers: Backend services can set custom headers that reach frontend clients
- Seamless Integration: Works with existing gateway configurations
Quick Start:
// Backend gRPC service setting metadata
func (s *Service) SomeMethod(ctx context.Context, req *pb.Request) (*pb.Response, error) {
// Set headers that will be forwarded to HTTP response
err := grpc.SendHeader(ctx, metadata.Pairs(
"X-Custom-Header", "custom-value",
"X-Trace-ID", "trace-12345",
))
if err != nil {
return nil, err
}
// Set trailers that will also be forwarded
grpc.SetTrailer(ctx, metadata.Pairs(
"X-Server-Info", "grpc-backend-v1",
"X-Processing-Time", "150ms",
))
return &pb.Response{}, nil
}
// Frontend HTTP client will now receive these headers:
// X-Custom-Header: custom-value
// X-Trace-ID: trace-12345
// X-Server-Info: grpc-backend-v1
// X-Processing-Time: 150ms
๐ Bug Fixes
1. ETCD Auto-Registration Fix
Resolved service discovery reliability issues
Problem Fixed: Services failing to auto-re-register when ETCD keys disappeared.
Impact: Improved service discovery reliability and automatic recovery.
Before vs After:
// Before: Manual re-registration required
// After: Automatic recovery
config := etcd.EtcdConf{
Hosts: []string{"localhost:2379"},
Key: "user.rpc",
// Auto-recovery now works reliably
}
2. SSE Timeout Configuration
Fixed Server-Sent Events timeout handling
Problem Fixed: SSE connections affected by http.Server's WriteTimeout causing premature disconnections.
Solution: SSE now properly handles timeouts independently of server write timeout.
// SSE now works correctly with server timeouts
server := &http.Server{
WriteTimeout: 10 * time.Second, // Won't affect SSE
}
// SSE connections maintain their own timeout handling
http.HandleFunc("/events", func(w http.ResponseWriter, r *http.Request) {
// SSE stream works regardless of server WriteTimeout
sse.StreamEvents(w, r, eventSource)
})
3. Environment Variable Unmarshaling
Fixed configuration loading from environment variables
Problem Fixed: Issues with unmarshaling environment variables for type time.Duration
.
Example Fix:
type Config struct {
Timeout time.Duration `json:",env=TIMEOUT"` // Now works correctly
}
4. Memory Optimization for Large Requests
Reduced memory usage in detailed request logging
Problem Fixed: Large memory consumption when logging POST request details.
Impact: Significantly reduced memory footprint for applications with large request bodies when setting log to verbose.
5. JSON Serialization HTML Escaping
Fixed HTML escaping issues in httpx responses
Problem Fixed: Unwanted HTML escaping during JSON serialization causing malformed responses.
Before:
{"message": "Hello \\u003cworld\\u003e"} // Incorrect escaping
After:
{"message": "Hello <world>"} // Correct output
6. Concurrent Resource Access Fix
Fixed race conditions in ImmutableResource
Problem Fixed: Concurrent access to ImmutableResource could lead to empty results.
Impact: Improved thread safety and reliability in high-concurrency scenarios.
โก Performance Improvements
Optimized Field Logging
Enhanced logging performance with structured field handling.
Improvement: Faster log processing with reduced allocations.
Usage:
// Optimized field logging
logx.Infow("User action",
logx.Field("user_id", userID),
logx.Field("action", "login"),
logx.Field("timestamp", time.Now()),
)
๐ฏ Migration Guide
From v1.8.5 to v1.9.0
- Update Dependencies:
go get github.com/zeromicro/go-zero@v1.9.0
MongoDB Driver:
- Update imports from zero-contrib if using MongoDB v1
- Consider migrating to v2 for better performance
Consumer Groups:
- Update Redis stream processing to use new consumer group APIs
๐ New Contributors
Welcome to our amazing new contributors who made their first contributions:
- @Twilikiss - Documentation improvements
- @charmfocus - sqlx field tagging enhancement
- @csbzy - SSE timeout fix
- @DengY11 - Gateway middleware architecture
- @queryfast - Performance optimizations
- @sunhao1296 - Concurrent resource fix
- @ipinak - Testing improvements
๐ Additional Resources
๐ Links
- Full Changelog: https://github.com/zeromicro/go-zero/compare/v1.8.5...v1.9.0
- Documentation: https://go-zero.dev/
- Community: https://github.com/zeromicro/go-zero/discussions
Happy coding with go-zero v1.9.0! ๐