Skip to content

feat(werror): 添加param参数以及携带params参数的function函数#2

Merged
NexZhu merged 1 commit intodaotl:mainfrom
Zfangzheng:main
Dec 25, 2025
Merged

feat(werror): 添加param参数以及携带params参数的function函数#2
NexZhu merged 1 commit intodaotl:mainfrom
Zfangzheng:main

Conversation

@Zfangzheng
Copy link

@Zfangzheng Zfangzheng commented Dec 25, 2025

  • 实现 ConvertToWError 函数,内部使用go底层优化的断言进行类型判断
  • 扩展 WError 接口,添加 SetDetails、GetParams、SetParams 和 SetMessage 方法
  • 在 Err 结构体中添加 params 字段用于存储参数信息
  • 实现 NewErrWithParams 函数,支持创建带参数的错误
  • 添加 GetParams 和 SetParams 方法的完整实现
  • 为 Err 结构体初始化 Details 和 params 字段为 nil

Description

Type of Change

  • 📚 Documentation (Non-breaking change; Changes in the documentation)
  • 🔧 Bug fix (Non-breaking change; Fixes an existing bug)
  • 🥂 Improvement (Non-breaking change; Improves existing feature)
  • 🚀 New feature (Non-breaking change; Adds functionality)
  • 🔐 Security fix (Non-breaking change; Patches a security issue)
  • 💥 Breaking change (Breaks existing functionality)

Checklist

  • I've read the Code of Conduct and this pull request adheres to it.
  • I've read the CONTRIBUTING.md guide.
  • I've run the complete test-suite using make test-suite, and it passed with no errors.
  • I've written new tests for all changes introduced in this pull request (where applicable).
  • I've documented any new methods/structures/packages added.

Review Process

Reviewees:

  1. Prefer incremental and appropriately-scoped changes.
  2. Leave a comment on things you want explicit feedback on.
  3. Respond clearly to comments and questions.

Reviewers:

  1. Test functionality using the criteria above.
  2. Offer tips for efficiency, feedback on best practices, and possible alternative approaches.
  3. For shorter, "quick" PRs, use your best judgment on the previous point.
  4. Use a collaborative approach and provide resources and/or context where appropriate.
  5. Provide screenshots/grabs where appropriate to show findings during review.
  6. In case of a potential bug in PR, be sure to add steps to reproduce the issue (where applicable)

This change is Reviewable

Summary by CodeRabbit

Release Notes

  • New Features
    • Error handling system now supports storing and retrieving contextual parameters with errors.
    • Enhanced error creation with ability to attach parameters for richer error context.
    • New methods enable flexible modification of error messages, details, and associated parameters after creation.

✏️ Tip: You can customize this high-level summary in your review settings.

- 实现 ConvertToWError 函数,内部使用go底层优化的断言进行类型判断
- 扩展 WError 接口,添加 SetDetails、GetParams、SetParams 和 SetMessage 方法
- 在 Err 结构体中添加 params 字段用于存储参数信息
- 实现 NewErrWithParams 函数,支持创建带参数的错误
- 添加 GetParams 和 SetParams 方法的完整实现
- 为 Err 结构体初始化 Details 和 params 字段为 nil
@coderabbitai
Copy link

coderabbitai bot commented Dec 25, 2025

📝 Walkthrough

Walkthrough

The werror package's error type gains parameter storage capabilities and expanded interface methods. A new conversion function standardizes input handling, while new accessor/mutator methods enable setting and retrieving error parameters, messages, and details.

Changes

Cohort / File(s) Summary
Error Type Enhancement
werror/error.go
Added params map[string]any field to Err struct. Expanded WError interface with SetDetails(), SetMessage(), GetParams(), and SetParams() methods. Implemented accessor/mutator methods on *Err with defensive copying for GetParams() and nil-safe handling in SetParams().
Error Creation & Conversion
werror/error.go
Added ConvertToWError(x interface{}) *Err to standardize arbitrary input conversion, preserving existing *Err or wrapping non-errors. Added NewErrWithParams(base *Err, code string, params map[string]any, msgDetail string) *Err constructor. Updated NewBaseErr initialization to include params: nil.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Whiskers twitch with glee—
Error params now run free!
Set and get with care so true,
Details dance in all we do. 🎉

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is in Chinese and refers to adding param parameters and functions with params parameters, which directly aligns with the main changes in the changeset (adding params field, GetParams/SetParams methods, and NewErrWithParams function).
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
werror/error.go (3)

29-58: Consider handling WError interface implementations that aren't *Err.

The function checks for *Err concrete type but doesn't handle cases where x implements the WError interface through a different type. If another type implements WError, it will be wrapped as an internal server error rather than preserving its error semantics.

Also, the comment on line 55 is in Chinese while other comments in the file are in English—consider using consistent language.

🔎 Proposed enhancement to handle WError interface
 func ConvertToWError(x interface{}) *Err {
 	if x == nil {
 		return nil
 	}

 	if werr, ok := x.(*Err); ok {
 		return werr
 	}

+	// Handle other WError implementations
+	if werr, ok := x.(WError); ok {
+		return &Err{
+			error:      werr,
+			HttpStatus: werr.GetHttpStatus(),
+			Code:       werr.GetCode(),
+			Message:    werr.GetMessage(),
+			Details:    werr.GetDetails(),
+			params:     nil,
+		}
+	}
+
 	var rawErr error
 	switch v := x.(type) {
 	case error:
 		rawErr = v
 	default:
 		rawErr = fmt.Errorf("%v", x)
 	}

 	detailErr := &Err{
 		Message: rawErr.Error(),
 	}

 	return &Err{
 		error:      rawErr,
 		HttpStatus: ErrInternalServerError.HttpStatus,
 		Code:       ErrInternalServerError.Code,
 		Message:    ErrInternalServerError.Message,
-		Details:    []WError{detailErr}, // 有技术详情,非nil
+		Details:    []WError{detailErr}, // Has technical details, non-nil
 		params:     nil,
 	}
 }

218-220: Consider defensive copy for consistency with SetParams.

SetParams makes a defensive copy of the map, but SetDetails assigns the slice directly. For consistency and to prevent external mutations, consider copying the slice.

🔎 Proposed defensive copy
 func (e *Err) SetDetails(details []WError) {
-	e.Details = details
+	if details == nil {
+		e.Details = nil
+		return
+	}
+	e.Details = make([]WError, len(details))
+	copy(e.Details, details)
 }

233-242: Inconsistent nil handling in SetParams.

When params is nil, SetParams creates an empty map rather than setting e.params = nil. This creates an inconsistency:

  • After NewBaseErr, GetParams() returns nil
  • After SetParams(nil), GetParams() returns an empty map {}

If the intent is to clear params, consider setting to nil instead. If the intent is to ensure params is never nil after being set, document this behavior.

🔎 Option A: Set to nil when nil is passed
 func (e *Err) SetParams(params map[string]any) {
 	if params == nil {
-		e.params = make(map[string]any)
+		e.params = nil
 		return
 	}
 	e.params = make(map[string]any, len(params))
 	for k, v := range params {
 		e.params[k] = v
 	}
 }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9821ff4 and c60387e.

📒 Files selected for processing (1)
  • werror/error.go
🔇 Additional comments (5)
werror/error.go (5)

86-86: Clarify whether params should be JSON-serializable.

The params field lacks a JSON tag, so it won't be included in JSON serialization. If this is intentional (internal use only), consider adding a comment. If params should appear in API error responses, add json:"params,omitempty".


110-111: LGTM!

Explicit initialization of Details and params to nil improves code clarity.


212-214: LGTM!

Simple and straightforward setter implementation.


222-231: LGTM!

Good defensive copy implementation to prevent external mutations of the internal params map.


68-71: Adding methods to an existing interface is a breaking change for external implementations.

Adding SetDetails, GetParams, SetParams, and SetMessage to the WError interface will break any external types implementing it. No internal implementations were found in the codebase, but external users with custom WError implementations will need to update their code.

Comment on lines +168 to +185
func NewErrWithParams(base *Err, code string, params map[string]any, msgDetail string) *Err {
if strings.TrimSpace(code) == "" {
code = base.Code
}
msg := base.Message

detailErr := &Err{
Message: base.Message + msgDetail,
}
return &Err{
error: fmt.Errorf("%w: %s", base.error, msg),
HttpStatus: base.HttpStatus,
Code: code,
Message: msg,
Details: []WError{detailErr},
params: params,
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Inconsistent behavior: params not defensively copied, and message handling differs from NewErr.

Two issues:

  1. Direct map assignment (line 183): params is assigned directly without copying, but SetParams makes a defensive copy. This inconsistency could lead to unexpected mutations if the caller modifies the map after creating the error.

  2. Message inconsistency: Unlike NewErr which appends msgDetail to the outer Message with a : separator, here msgDetail only appears in detailErr.Message (line 175), and the outer Message (line 181) excludes it. Also, detailErr concatenates without a separator.

🔎 Proposed fix for consistency
 func NewErrWithParams(base *Err, code string, params map[string]any, msgDetail string) *Err {
 	if strings.TrimSpace(code) == "" {
 		code = base.Code
 	}
 	msg := base.Message
+	msgDetail = strings.TrimSpace(msgDetail)
+	if msgDetail != "" {
+		msg = msg + ": " + msgDetail
+	}

 	detailErr := &Err{
-		Message: base.Message + msgDetail,
+		Message: msg,
 	}
+
+	// Defensive copy of params
+	var paramsCopy map[string]any
+	if params != nil {
+		paramsCopy = make(map[string]any, len(params))
+		for k, v := range params {
+			paramsCopy[k] = v
+		}
+	}
+
 	return &Err{
 		error:      fmt.Errorf("%w: %s", base.error, msg),
 		HttpStatus: base.HttpStatus,
 		Code:       code,
-		Message:    msg,
+		Message:    msg,
 		Details:    []WError{detailErr},
-		params:     params,
+		params:     paramsCopy,
 	}
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func NewErrWithParams(base *Err, code string, params map[string]any, msgDetail string) *Err {
if strings.TrimSpace(code) == "" {
code = base.Code
}
msg := base.Message
detailErr := &Err{
Message: base.Message + msgDetail,
}
return &Err{
error: fmt.Errorf("%w: %s", base.error, msg),
HttpStatus: base.HttpStatus,
Code: code,
Message: msg,
Details: []WError{detailErr},
params: params,
}
}
func NewErrWithParams(base *Err, code string, params map[string]any, msgDetail string) *Err {
if strings.TrimSpace(code) == "" {
code = base.Code
}
msg := base.Message
msgDetail = strings.TrimSpace(msgDetail)
if msgDetail != "" {
msg = msg + ": " + msgDetail
}
detailErr := &Err{
Message: msg,
}
// Defensive copy of params
var paramsCopy map[string]any
if params != nil {
paramsCopy = make(map[string]any, len(params))
for k, v := range params {
paramsCopy[k] = v
}
}
return &Err{
error: fmt.Errorf("%w: %s", base.error, msg),
HttpStatus: base.HttpStatus,
Code: code,
Message: msg,
Details: []WError{detailErr},
params: paramsCopy,
}
}
🤖 Prompt for AI Agents
In werror/error.go around lines 168-185, make NewErrWithParams consistent with
NewErr: defensively copy the incoming params map into a newly allocated map and
assign that copy to params to avoid external mutation; build the outer Message
by appending msgDetail to base.Message using the same ": " separator logic
NewErr uses (only when msgDetail is non-empty), set detailErr.Message
consistently (use the same concatenation pattern or the same base+detail
formatting used elsewhere), and update the fmt.Errorf call to include the final
outer message variable (not the original base.Message) so the returned error
text matches the Message field.

@NexZhu NexZhu merged commit c60387e into daotl:main Dec 25, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants