zeromicro/go-zero
 Watch   
 Star   
 Fork   
1 days ago
go-zero

v1.9.3

We are excited to announce the release of go-zero v1.9.3! This release brings several important enhancements and bug fixes that improve the framework's reliability, performance, and alignment with industry best practices.

🎉 Highlights

  • Consistent Hash Load Balancing: New gRPC load balancer for session affinity
  • gRPC Best Practices: Changed NonBlock default to align with gRPC recommendations
  • Improved Distributed Tracing: Fixed gateway trace header propagation
  • ORM Improvements: Fixed zero value scanning for pointer destinations

✨ New Features

Consistent Hash Balancer Support (#5246)

Contributor: @zhoushuguang

A new consistent hash load balancer has been added to the zRPC package, enabling session affinity for gRPC services.

Key Features:

  • Hash-based request routing to maintain session affinity
  • Distributes requests based on a hash key from context
  • Minimal request redistribution on node changes
  • Built on go-zero's existing core/hash/ConsistentHash implementation

Usage Example:

// Set hash key in context
ctx := zrpc.SetHashKey(ctx, "user_123")

// Requests with the same key will be routed to the same backend
resp, err := client.SomeMethod(ctx, req)

Configuration:

c := zrpc.RpcClientConf{
    Endpoints: []string{"localhost:8080", "localhost:8081"},
    BalancerName: "consistent_hash",  // Use consistent hash balancer
}

Benefits:

  • Enables stateful service interactions
  • Improves cache hit rates on backend services
  • Reduces session data synchronization overhead
  • Maintains load distribution while supporting affinity

🐛 Bug Fixes

Fixed Gateway Trace Headers (#5256, #5248)

Contributor: @kevwan

Fixed an issue where OpenTelemetry trace propagation headers were not being properly forwarded through the gateway to upstream gRPC services, breaking distributed tracing.

Problem: The gateway was not forwarding critical W3C Trace Context headers (traceparent, tracestate, baggage) to gRPC metadata, causing trace context to be lost at the gateway boundary.

Solution:

  • Enhanced ProcessHeaders function to forward trace propagation headers
  • Headers are now properly converted to lowercase per gRPC metadata conventions
  • Maintains distributed tracing across HTTP → gRPC boundaries

Impact:

  • End-to-end tracing now works correctly through the gateway
  • Improved observability for microservice architectures
  • Better debugging and performance analysis capabilities

Technical Details:

// Trace headers now properly forwarded
var traceHeaders = map[string]bool{
    "traceparent": true,  // W3C Trace Context
    "tracestate":  true,  // Additional trace state
    "baggage":     true,  // W3C Baggage propagation
}

Fixed Multiple Trace Initialization (#5244)

Contributor: @kevwan

Problem: When running multiple services (e.g., REST + RPC) in the same process, the trace agent could be initialized multiple times, potentially causing resource leaks or unexpected behavior.

Solution:

  • Used sync.Once to ensure trace agent is initialized only once
  • Aligned with similar patterns used in prometheus.StartAgent and logx.SetUp
  • Added sync.OnceFunc for shutdown to prevent double cleanup

Code Changes:

var (
    once           sync.Once
    shutdownOnceFn = sync.OnceFunc(func() {
        if tp != nil {
            _ = tp.Shutdown(context.Background())
        }
    })
)

func StartAgent(c Config) {
    if c.Disabled {
        return
    }

    once.Do(func() {
        if err := startAgent(c); err != nil {
            logx.Error(err)
        }
    })
}

Benefits:

  • Prevents resource conflicts in multi-server processes
  • Ensures single global tracer provider instance
  • Safer concurrent initialization
  • Proper cleanup on shutdown

Fixed ORM Zero Value Scanning for Pointer Destinations (#5270)

Contributor: @lerity-yao (first contribution! 🎊)

Problem: When scanning database results into struct fields with pointer types, zero values (0, false, empty string) were not being properly distinguished from NULL values. This caused nil pointers to be set to zero values incorrectly.

Solution: Enhanced the getValueInterface function to properly initialize nil pointers before scanning, ensuring the SQL driver can correctly populate them with zero or non-zero values.

Code Changes:

func getValueInterface(value reflect.Value) (any, error) {
    if !value.CanAddr() || !value.Addr().CanInterface() {
        return nil, ErrNotReadableValue
    }

    // Initialize nil pointer before scanning
    if value.Kind() == reflect.Pointer && value.IsNil() {
        baseValueType := mapping.Deref(value.Type())
        value.Set(reflect.New(baseValueType))
    }

    return value.Addr().Interface(), nil
}

Impact:

type User struct {
    Name    string   `db:"name"`      // Always set
    Age     *int     `db:"age"`       // Can distinguish NULL vs 0
    Active  *bool    `db:"active"`    // Can distinguish NULL vs false
}

// Before: age=0 and age=NULL both resulted in nil pointer
// After:  age=0 → *int(0), age=NULL → nil pointer ✓

Benefits:

  • Correct handling of NULL vs zero values
  • Better semantic representation of optional fields
  • Prevents unexpected nil pointer dereferences
  • Aligns with Go's SQL scanning best practices

🔄 Breaking Changes (With Backward Compatibility)

Changed NonBlock Default to True (#5259)

Contributor: @kevwan

Motivation: Aligned with gRPC official best practices which discourage blocking dials.

Change:

// zrpc/config.go
type RpcClientConf struct {
    // Before: NonBlock bool `json:",optional"`
    // After:
    NonBlock bool `json:",default=true"`  // Now defaults to true
}

Why This Matters:

  1. Blocking dials are deprecated: grpc.WithBlock() is an anti-pattern
  2. Connection state is dynamic: Being connected at dial time doesn't guarantee future connectivity
  3. RPCs handle waiting: All RPCs automatically wait until connection or deadline
  4. Simpler code: No need to check "ready" state before making calls

Migration Guide:

For most users, no action required - the new default is the recommended behavior.

If you explicitly need blocking behavior (not recommended):

// Option 1: Configuration
c := zrpc.RpcClientConf{
    NonBlock: false,  // Explicit blocking
}

// Option 2: Client option (deprecated)
client := zrpc.MustNewClient(c, zrpc.WithBlock())

Backward Compatibility:

  • Existing configs with NonBlock: false continue to work
  • New WithBlock() option available (marked deprecated)
  • No changes needed for services already using NonBlock: true

Documentation: See GRPC_NONBLOCK_CHANGE.md for detailed migration guide and rationale.


👥 New Contributors

We're thrilled to welcome new contributors to the go-zero community! 🎉

  • @JackGod001 - Made their first contribution in #4343
  • @stemlaud - Made their first contribution in #5245
  • @gfischer7 - Made their first contribution in #5254
  • @lerity-yao - Made their first contribution in #5270 (ORM fix)

Thank you for your contributions! We look forward to your continued involvement in the project.


📦 Installation & Upgrade

Install

go get -u github.com/zeromicro/go-zero@v1.9.3

Update

# Update go.mod
go get -u github.com/zeromicro/go-zero@v1.9.3
go mod tidy

🔗 Links


📝 Detailed Changes

Core Enhancements

Load Balancing

  • Added consistent hash balancer for gRPC (zrpc/internal/balancer/consistenthash)
  • Context-based hash key API: SetHashKey() and GetHashKey()
  • Configurable replica count and hash function
  • Comprehensive test coverage

Distributed Tracing

  • Fixed trace header propagation in gateway
  • Proper handling of W3C Trace Context headers
  • Case-insensitive header matching per gRPC conventions
  • Single initialization with sync.Once pattern

ORM/Database

  • Fixed pointer field scanning for zero values
  • Proper NULL vs zero value distinction
  • Enhanced getValueInterface() with nil pointer initialization
  • Support for sql.Null* types

gRPC Client

  • Changed NonBlock default to true
  • Added deprecated WithBlock() option for compatibility
  • Explicit handling of both blocking and non-blocking modes
  • Updated client initialization logic

Testing & Quality

  • Added comprehensive test coverage for all changes
  • Edge case handling in ORM tests
  • Gateway trace header test cases
  • Consistent hash balancer benchmarks

🙏 Acknowledgments

Special thanks to all contributors, issue reporters, and community members who made this release possible. Your feedback and contributions continue to make go-zero better!


💬 Feedback

If you encounter any issues or have suggestions for future releases, please:

Happy coding with go-zero! 🚀

2025-10-12 11:55:57
go-zero

goctl/v1.9.2

What's Changed

  • Swagger Improvements:

    • Fix swagger path generation: remove trailing slash for root routes with prefix #5212 (@Copilot)
    • Fix swagger generation: info block and server tags not included #5215 (@Copilot)
    • Restore API summaries in swagger generation #5237 (@kevwan)
  • Other Fixes:

    • Fix: issue #5154, not using SSE template files #5220 (@kevwan)

New Contributors

  • @rizkyikiw42 made their first contribution in #5210
  • @ZH1995 made their first contribution in #5233

Full Changelog: tools/goctl/v1.9.1...tools/goctl/v1.9.2

2025-10-11 16:20:23
go-zero

v1.9.2

Overview

This release is solely focused on addressing a critical problem related to the go-redis dependency. Previous versions of go-redis were retracted, which could cause build failures, dependency resolution issues, or unexpected behavior for downstream projects relying on stable releases.

What's Fixed

  • go-redis Version Issue: The only change in this release is updating go-redis to circumvent the retracted versions. This ensures that consumers of this library can continue to build and use it reliably without encountering problems from retracted dependencies.
    • Chore: update go-redis for the retracted versions (#5235) by @kevwan

Impact

  • No Functional Changes: There are no new features, bug fixes, or breaking changes in this release. Functionality remains the same as the previous version.
  • Dependency Stability: Users should upgrade to this release if they are experiencing issues related to go-redis retractions or want to ensure their dependency tree remains stable.

New Contributors

While this release only addresses the go-redis issue, we'd like to acknowledge recent first-time contributors to the project:

Changelog

For a full list of changes between v1.9.1 and v1.9.2, see the changelog.


Upgrade Recommendation:
If you depend on redis, it is strongly recommended to upgrade to this release to avoid issues caused by the retracted versions.

2025-10-02 22:48:57
go-zero

goctl/v1.9.1

Highlights

  • Code generation ergonomics:
    • Add code generation headers to safe-to-edit files for clearer ownership and customization boundaries.
    • Fix array type generation issues to ensure accurate code output.
  • API developer experience:
    • Add complete test scaffolding for API projects via the --test flag.
  • Swagger/OpenAPI correctness:
    • Correct $ref placement in array definitions when useDefinitions is enabled.
  • Stability and optimizations:
    • Fix SSE handler blocking.
    • Optimize slice lookups and Unquote utility function performance.

Detailed Changes

Code Generation

  • Add code generation headers in safe-to-edit files to clarify which files are intended for user modifications while keeping generated segments intact.
    PR: feat: add code generation headers in safe to edit files by @kevwan (@5136)
  • Fix array type generation error to produce correct types in generated code.
    PR: fix array type generation error by @kesonan (@5142)

API/CLI

  • Add complete test scaffolding support for API projects using the --test flag, enabling quicker setup of testable services.
    PR: Add complete test scaffolding support with --test flag for API projects by @Copilot (@5176)

Swagger/OpenAPI

  • Fix $ref placement in array definitions when useDefinitions is enabled to align with the OpenAPI/Swagger schema expectations.
    PR: fix(goctl/swagger): correct $ref placement in array definitions when useDefinitions is enabled by @Copilot (@5199)

Stability

  • Fix SSE handler blocking behavior that could stall event delivery under certain conditions.
    PR: fix: SSE handler blocking by @wuqinqiang (@5181)

Performance and Utilities

  • Optimize slice find routines and the Unquote function for better runtime efficiency.
    PR: update: optimize slice find and Unquote func by @me-cs (@5108)

Upgrade Notes

  • Swagger regeneration: If you rely on useDefinitions, regenerate your Swagger/OpenAPI specs to pick up the corrected $ref placement.
  • Codegen headers: Newly generated safe-to-edit files will include headers clarifying edit expectations; no action required, but helpful for code review and maintenance.

Acknowledgements

  • Thanks to all contributors in this release: @kevwan, @kesonan, @me-cs, @wuqinqiang, and first-time contributor @Copilot. Your improvements enhance correctness, stability, and developer productivity for goctl users.

Full Changelog

2025-10-02 22:11:18
go-zero

v1.9.1

Highlights

  • Logging enhancements:
    • Customize log key names to fit your log schema and downstream tooling.
    • Prefer json.Marshaler over fmt.Stringer when emitting JSON logs, improving correctness and structure.
  • REST/SSE stability and operability:
    • Fix SSE handler blocking and reduce noisy logs by downgrading SetWriteDeadline errors to debug.
    • Add SetSSESlowThreshold to help detect slow clients and long writes.
  • Diagnostics and performance:
    • Improved mapreduce panic stacktraces for faster root-cause analysis.
    • Optimized machine performance data reading to reduce runtime overhead.

Detailed Changes

Logging

  • Support customizing log keys so you can align emitted fields (e.g., time, level, caller, message) to your organization’s conventions or ingestion pipeline requirements.
    PR: feat: support customize of log keys by @WqyJh (@5103)
  • Prefer json.Marshaler over fmt.Stringer when generating JSON logs, ensuring structured fields are serialized using their explicit JSON representations rather than ad-hoc strings.
    PR: feat: prefer json.Marshaler over fmt.Stringer for JSON log output by @WqyJh (@5117)

REST/SSE

  • Fix SSE handler blocking behavior that could stall responses under certain conditions.
    PR: fix: SSE handler blocking by @wuqinqiang (@5181)
  • Reduce log noise for transient I/O conditions by downgrading SetWriteDeadline errors to debug level in REST SSE.
    PR: fix(rest): change SSE SetWriteDeadline error log to debug level by @wuqinqiang (@5162)
  • Add sseSlowThreshold to surface slow SSE writes, enabling better observability about backpressure or slow clients.
    PR: feat(handler): add sseSlowThreshold by @wuqinqiang (@5196)

MapReduce

  • Improve panic stacktrace reporting in mapreduce, making error contexts clearer and debugging faster.
    PR: optimize: mapreduce panic stacktrace by @kevwan (@5168)

Performance and Runtime

  • Optimize machine performance data reading to lower collection overhead and reduce runtime impact.
    PR: opt: optimization of machine performance data reading by @wanwusangzhi (@5174)

Bug Fixes

  • Fix gRPC → HTTP mapping issue in gateway.
    PR: fix: issue-5110 by @guonaihong (@5113)

Migration and Usage Notes

  • Logging key customization:
    • If you rely on specific field names in log pipelines, consider setting the new custom key configuration to preserve schema consistency.
  • JSON log output:
    • If your types implement json.Marshaler, expect more accurate JSON in logs. If you previously depended on stringified representations, review downstream consumers to ensure compatibility.
  • SSE tuning:
    • Consider using SetSSESlowThreshold to flag slow clients or network conditions in environments sensitive to latency.
    • The SetWriteDeadline log level change reduces noise; adjust logger settings if you still want to surface these events.

Acknowledgements

  • Thanks to all contributors in this release: @WqyJh, @guonaihong, @wanwusangzhi, @kevwan, @wuqinqiang, and first-time contributor @Copilot. Your work improves performance, reliability, and developer ergonomics for everyone using go-zero.

Full Changelog

2025-08-31 23:37:00
go-zero

goctl/v1.9.0

What's Changed

New Contributors

Full Changelog: https://github.com/zeromicro/go-zero/compare/tools/goctl/v1.8.5...tools/goctl/v1.9.0

2025-08-17 17:50:38
go-zero

goctl/v1.9.0-alpha

What's Changed

New Contributors

Full Changelog: https://github.com/zeromicro/go-zero/compare/tools/goctl/v1.8.5...tools/goctl/v1.9.0-alpha

2025-08-15 20:08:02
go-zero

v1.9.0

What's Changed

  • feat: support masking sensitive data in logx by @kevwan in #5003
  • feat: add field tag (-) skip logic in unwrapFields in sqlx by @charmfocus in #5010
  • feat: upgrade to mongo-driver v2, and move v1 to zero-contrib by @me-cs in #4687
  • feat: add generic TypedSet with 2x performance boost and compile-time by @codeErrorSleep in #4888
  • feat: add custom middleware support with onion model in gateway by @DengY11 in #5035
  • feat: redis support consumer groups by @jk2K in #4912
  • feat: ignore unknown fields in gateway request parsing by @guonaihong in #5058
  • fix: issue with etcd key disappearing and unable to auto-re-register by @guonaihong in #4960
  • fix: SSE timeout will affected by http.Server's WriteTimeout by @csbzy in #5024
  • fix: unmarshal problem on env vars for type env string by @kevwan in #5037
  • fix: large memory usage on detail logging post requests by @kevwan in #5039
  • fix: Resolve HTML escaping issue during JSON serialization in httpx by @Disdjj in #5032
  • fix: resolve concurrent get may lead to empty result in ImmutableResource by @sunhao1296 in #5065
  • optimize: logging with fields by @kevwan in #5066

New Contributors

Detailed Release Notes: https://go-zero.dev/en/reference/releases/v1.9.0 Full Changelog: https://github.com/zeromicro/go-zero/compare/v1.8.5...v1.9.0

2025-07-13 11:18:51
go-zero

goctl/v1.8.5

What's Changed

  • Bug Fix: Fix for issue #4943 — fix goctl api swagger error (@kesonan)
  • Bug Fix: Fixed goctl api swagger panic with nil pointer when there is a wrong field tag in the API file (#4936)
  • Bug Fix: Resolved issue where timeout: 0s was not working in API files (#4932, @kevwan)
  • Bug Fix: Corrected PostgreSQL numeric type mapping in goctl model generation (#4992, @AnlynnLee)
  • Enhancement: Improved POST JSON parameter determination logic in goctl API Swagger and added unit tests (#4997, @Twilikiss)

New Contributors

  • @wanwusangzhi made their first contribution (#4944)
  • @geekeryy made their first contribution (#4979)
  • @Twilikiss made their first contribution (#4997)

Full Changelog: tools/goctl/v1.8.4...tools/goctl/v1.8.5

2025-07-13 00:00:52
go-zero

v1.8.5

Features

  • SQL Read/Write Splitting: Introduced SQL read/write splitting for improved database performance and scalability (#4976, #4990, #5000).
  • Serverless Support in REST: Added support for serverless use in REST services (#5001).

Bug Fixes & Improvements

  • Fixed HTTP SSE method timeout not working when timeout is set by server (#4932)
  • Fixed timeout 0s not working in API files (#4932)
  • Fixed panic caused by time.Duration type with numerical values (#4944)
  • Fixed duration type comparison in environment variable processing (#4979)

New Contributors

  • @wanwusangzhi made their first contribution (#4944)
  • @geekeryy made their first contribution (#4979)

Full Changelog: v1.8.4...v1.8.5