When business requirements call for complex error code definitions, it is recommended to flexibly use the Detail parameter of error codes for extending error code functionality.

Let’s look at an example that primarily implements the following features:

  • Use middleware to identify the execution results of route functions and obtain the error code information returned by these functions, returning the error code information as part of the response to the caller.
  • If an error occurs, record the current user information causing the error into the logs. This is achieved using the Detail extension parameter.

Business Error Codes

Error Code Definition

  1. type BizCode struct {
  2. User User
  3. // ...
  4. }
  5. type User struct {
  6. Id int
  7. Name string
  8. // ...
  9. }

Using Error Codes

In most scenarios of error code extension, the gcode.WithCode method is required:

  1. // WithCode creates and returns a new error code based on given Code.
  2. // The code and message is from given `code`, but the detail if from given `detail`.
  3. func WithCode(code Code, detail interface{}) Code

Thus, our custom extension can be used as follows:

  1. code := gcode.WithCode(gcode.CodeNotFound, BizCode{
  2. User: User{
  3. Id: 1,
  4. Name: "John",
  5. },
  6. })
  7. fmt.Println(code)

That is, in error codes, we can inject some customized error code extension data according to business scenarios to facilitate further processing by the upper layer.

Modifying Middleware

We will apply the custom error codes above in a request return middleware, allowing the top-layer business logic to obtain the details corresponding to the error code for further business processing. The data structure returned by the middleware can also be customized, such as the code field which may not necessarily be an integer, and can be fully customized.

  1. func ResponseHandler(r *ghttp.Request) {
  2. r.Middleware.Next()
  3. // There's custom buffer content, it then exits current handler.
  4. if r.Response.BufferLength() > 0 {
  5. return
  6. }
  7. var (
  8. err = r.GetError()
  9. res = r.GetHandlerResponse()
  10. code = gerror.Code(err)
  11. )
  12. if code == gcode.CodeNil && err != nil {
  13. code = gcode.CodeInternalError
  14. }
  15. if detail, ok := code.Detail().(BizCode); ok {
  16. g.Log().Errorf(r.Context(), `error caused by user "%+v"`, detail.User)
  17. }
  18. r.Response.WriteJson(ghttp.DefaultHandlerResponse{
  19. Code: gcode.CodeOK.Code(),
  20. Message: gcode.CodeOK.Message(),
  21. Data: res,
  22. })
  23. }

Error Code - Extension - 图1tip

The Detail data is automatically printed in the default logs of the Server framework.