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.
- 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
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/ConsistentHashimplementation
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
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
ProcessHeadersfunction 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
}
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.Onceto ensure trace agent is initialized only once - Aligned with similar patterns used in
prometheus.StartAgentandlogx.SetUp - Added
sync.OnceFuncfor 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
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
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:
- Blocking dials are deprecated:
grpc.WithBlock()is an anti-pattern - Connection state is dynamic: Being connected at dial time doesn't guarantee future connectivity
- RPCs handle waiting: All RPCs automatically wait until connection or deadline
- 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: falsecontinue 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.
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.
go get -u github.com/zeromicro/go-zero@v1.9.3
# Update go.mod
go get -u github.com/zeromicro/go-zero@v1.9.3
go mod tidy
- Full Changelog: https://github.com/zeromicro/go-zero/compare/v1.9.2...v1.9.3
- Documentation: https://go-zero.dev
- GitHub Repository: https://github.com/zeromicro/go-zero
- Added consistent hash balancer for gRPC (
zrpc/internal/balancer/consistenthash) - Context-based hash key API:
SetHashKey()andGetHashKey() - Configurable replica count and hash function
- Comprehensive test coverage
- Fixed trace header propagation in gateway
- Proper handling of W3C Trace Context headers
- Case-insensitive header matching per gRPC conventions
- Single initialization with
sync.Oncepattern
- Fixed pointer field scanning for zero values
- Proper NULL vs zero value distinction
- Enhanced
getValueInterface()with nil pointer initialization - Support for
sql.Null*types
- Changed NonBlock default to true
- Added deprecated
WithBlock()option for compatibility - Explicit handling of both blocking and non-blocking modes
- Updated client initialization logic
- Added comprehensive test coverage for all changes
- Edge case handling in ORM tests
- Gateway trace header test cases
- Consistent hash balancer benchmarks
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!
If you encounter any issues or have suggestions for future releases, please:
- Open an issue: https://github.com/zeromicro/go-zero/issues
Happy coding with go-zero! 🚀
goctl/v1.9.2
-
Swagger Improvements:
-
Other Fixes:
- Fix: issue #5154, not using SSE template files #5220 (@kevwan)
Full Changelog: tools/goctl/v1.9.1...tools/goctl/v1.9.2
v1.9.2
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.
- 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.
- 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.
While this release only addresses the go-redis issue, we'd like to acknowledge recent first-time contributors to the project:
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.
goctl/v1.9.1
- 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
--testflag.
- Add complete test scaffolding for API projects via the
- Swagger/OpenAPI correctness:
- Correct
$refplacement in array definitions whenuseDefinitionsis enabled.
- Correct
- Stability and optimizations:
- Fix SSE handler blocking.
- Optimize slice lookups and
Unquoteutility function performance.
- 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)
- Add complete test scaffolding support for API projects using the
--testflag, enabling quicker setup of testable services.
PR: Add complete test scaffolding support with --test flag for API projects by @Copilot (@5176)
- Fix
$refplacement in array definitions whenuseDefinitionsis 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)
- Fix SSE handler blocking behavior that could stall event delivery under certain conditions.
PR: fix: SSE handler blocking by @wuqinqiang (@5181)
- Optimize slice find routines and the
Unquotefunction for better runtime efficiency.
PR: update: optimize slice find and Unquote func by @me-cs (@5108)
- Swagger regeneration: If you rely on
useDefinitions, regenerate your Swagger/OpenAPI specs to pick up the corrected$refplacement. - Codegen headers: Newly generated safe-to-edit files will include headers clarifying edit expectations; no action required, but helpful for code review and maintenance.
- 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.
v1.9.1
- Logging enhancements:
- Customize log key names to fit your log schema and downstream tooling.
- Prefer
json.Marshaleroverfmt.Stringerwhen emitting JSON logs, improving correctness and structure.
- REST/SSE stability and operability:
- Fix SSE handler blocking and reduce noisy logs by downgrading
SetWriteDeadlineerrors to debug. - Add
SetSSESlowThresholdto help detect slow clients and long writes.
- Fix SSE handler blocking and reduce noisy logs by downgrading
- Diagnostics and performance:
- Improved mapreduce panic stacktraces for faster root-cause analysis.
- Optimized machine performance data reading to reduce runtime overhead.
- 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.Marshaleroverfmt.Stringerwhen 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)
- 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
SetWriteDeadlineerrors to debug level in REST SSE.
PR: fix(rest): change SSE SetWriteDeadline error log to debug level by @wuqinqiang (@5162) - Add
sseSlowThresholdto surface slow SSE writes, enabling better observability about backpressure or slow clients.
PR: feat(handler): add sseSlowThreshold by @wuqinqiang (@5196)
- Improve panic stacktrace reporting in mapreduce, making error contexts clearer and debugging faster.
PR: optimize: mapreduce panic stacktrace by @kevwan (@5168)
- Optimize machine performance data reading to lower collection overhead and reduce runtime impact.
PR: opt: optimization of machine performance data reading by @wanwusangzhi (@5174)
- Fix gRPC → HTTP mapping issue in gateway.
PR: fix: issue-5110 by @guonaihong (@5113)
- 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.
- If your types implement
- SSE tuning:
- Consider using
SetSSESlowThresholdto flag slow clients or network conditions in environments sensitive to latency. - The
SetWriteDeadlinelog level change reduces noise; adjust logger settings if you still want to surface these events.
- Consider using
- 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.
goctl/v1.9.0
- fear: add uuid:varchar to p2m by @hoshi200 in https://github.com/zeromicro/go-zero/pull/5022
- feat: support sse in api files by @kevwan in https://github.com/zeromicro/go-zero/pull/5074
- feat: supported sse generation by @kesonan in https://github.com/zeromicro/go-zero/pull/5082
- feat: Support projectPkg template variables in config, handler, logic, main, and svc template files by @geekeryy in https://github.com/zeromicro/go-zero/pull/4939
- feat: support goctl --module to set go module by @kevwan in https://github.com/zeromicro/go-zero/pull/5135
- @charmfocus made their first contribution in https://github.com/zeromicro/go-zero/pull/5010
- @csbzy made their first contribution in https://github.com/zeromicro/go-zero/pull/5024
- @DengY11 made their first contribution in https://github.com/zeromicro/go-zero/pull/5035
- @queryfast made their first contribution in https://github.com/zeromicro/go-zero/pull/5051
- @sunhao1296 made their first contribution in https://github.com/zeromicro/go-zero/pull/5065
- @ipinak made their first contribution in https://github.com/zeromicro/go-zero/pull/5029
Full Changelog: https://github.com/zeromicro/go-zero/compare/tools/goctl/v1.8.5...tools/goctl/v1.9.0
goctl/v1.9.0-alpha
- fear: add uuid:varchar to p2m by @hoshi200 in https://github.com/zeromicro/go-zero/pull/5022
- feat: support sse in api files by @kevwan in https://github.com/zeromicro/go-zero/pull/5074
- feat: supported sse generation by @kesonan in https://github.com/zeromicro/go-zero/pull/5082
- @charmfocus made their first contribution in https://github.com/zeromicro/go-zero/pull/5010
- @csbzy made their first contribution in https://github.com/zeromicro/go-zero/pull/5024
- @DengY11 made their first contribution in https://github.com/zeromicro/go-zero/pull/5035
- @queryfast made their first contribution in https://github.com/zeromicro/go-zero/pull/5051
- @sunhao1296 made their first contribution in https://github.com/zeromicro/go-zero/pull/5065
- @ipinak made their first contribution in https://github.com/zeromicro/go-zero/pull/5029
Full Changelog: https://github.com/zeromicro/go-zero/compare/tools/goctl/v1.8.5...tools/goctl/v1.9.0-alpha
v1.9.0
- feat: support masking sensitive data in logx by @kevwan in #5003
- feat: add field tag (
-) skip logic inunwrapFieldsin sqlx by @charmfocus in #5010 - feat: upgrade to mongo-driver v2, and move v1 to
zero-contribby @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
- @Twilikiss made their first contribution in #4997
- @charmfocus made their first contribution in #5010
- @csbzy made their first contribution in #5024
- @DengY11 made their first contribution in #5035
- @queryfast made their first contribution in #5051
- @sunhao1296 made their first contribution in #5065
- @ipinak made their first contribution in #5029
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
goctl/v1.8.5
- 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: 0swas not working in API files (#4932, @kevwan) - Bug Fix: Corrected PostgreSQL
numerictype mapping in goctl model generation (#4992, @AnlynnLee) - Enhancement: Improved POST JSON parameter determination logic in goctl API Swagger and added unit tests (#4997, @Twilikiss)
- @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
v1.8.5
- 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).
- Fixed HTTP SSE method timeout not working when timeout is set by server (#4932)
- Fixed timeout
0snot working in API files (#4932) - Fixed panic caused by
time.Durationtype with numerical values (#4944) - Fixed duration type comparison in environment variable processing (#4979)
Full Changelog: v1.8.4...v1.8.5