ep

package module
v0.0.0-...-de44452 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 22, 2023 License: MIT Imports: 5 Imported by: 0

README

Error Packer

Go struct packer, specifically for handling errors

Why

The way Go handles errors will always end up with a bunch of if err!=nil, it's ok itself but when we have to return a struct every time an error occurs, it can take up a lot of lines which significantly decreases the readability and make typing work more tedious.

Take Gin framework as an example, the usual way to handle errors is something like this

func handler(c *gin.Context) {
    if err != nil {
       c.JSON(http.StatusOK, SomeStruct{
            Resp: Resp{
                Code: -1,
                Msg:  err.Error(),
            },
            Data: someData,
        })
        return
    }
}

After introducing the Error Packer (ep), it will become something like this

func handler(c *gin.Context) {
    packer := ep.Packer{V: SomeStruct{}}
    if err != nil {
        c.JSON(http.StatusOK, packer.Pack(err))
        return
    }
}

Much cleaner right? Let's get into it.

What does it do?

Packer

Packer is for "packing a struct". It will pack an ErrPack struct into any struct and fill the fields with tagged values.

ErrPack struct

ErrPack struct is an error information struct which implements the error type, it contains a code field and a message field. You can customize these fields as you want.

If you don't need a code field, you can also just pass the err (type error) into Packer, it accepts both types.

Usage

Copy the packer.go and err_pack.go file to wherever you want.

Define your struct with "ep" tags.

There are 4 meaningful tags, others stand for the default values of the fields:

  • ep:"err.code" - the field with this tag will be filled with ErrPack.Code, it must be int type
  • ep:"err.msg" - the field with this tag will be filled with ErrPack.Msg, it must be string type
  • ep:"" - the field with an empty tag will remain the default value of the type, you can also omit the tag
  • ep:"-" - the field with this tag will be forcefully ignored, this is useful when it comes to embedded struct (see explanation below)

Example

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    ep "github.com/zenpk/error-packer"
    "net/http"
    "net/http/httptest"
)

type User struct {
    Name string `json:"name,omitempty"`
}

type UserLoginResp struct {
    Seq  int64  `json:"seq" ep:"-1"`          // will be -1
    Code int64  `json:"code" ep:"err.code"`   // will eventually be ErrPack.Code
    Msg  string `json:"msg" ep:"err.msg"`     // will eventually be ErrPack.Msg
    User *User  `json:"user,omitempty" ep:""` // will omit this field
}

func handler(c *gin.Context) {
    // create a new packer your JSON interface
    packer := ep.Packer{V: UserLoginResp{}}
    err := ep.ErrInputBody      // assume that an input body error happened
    resp := packer.Pack(err)    // pack the response struct with the error
    c.JSON(http.StatusOK, resp) // return with resp
}

func main() {
    req, _ := http.NewRequest(http.MethodGet, "/err", nil) // make a mock request
    rec := httptest.NewRecorder()                          // record the mock request
    // use Gin to handle the request
    r := gin.Default()
    r.GET("/err", handler)
    r.ServeHTTP(rec, req)
    fmt.Println(rec.Body.String())
}
Output
{"seq":-1,"code":4003,"msg":"input body error"}

Embedded Struct

Error Packer supports embedded struct. However, every field must be exported, otherwise errors will occur. If you don't want Packer to traverse the whole embedded struct, you can add anep:"-"tag to a struct to ignore the field.

type Parent struct{
    children `ep:"-"` // if not adding the tag, Packer will go into the children struct which is not exported, and causing an error
    Others string
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrOK               = ErrPack{2000, "success"}
	ErrUnknown          = ErrPack{5900, "unknown error"}
	ErrNotLogin         = ErrPack{4001, "user not logged in error"}
	ErrNoPermission     = ErrPack{4002, "no permission error"}
	ErrInputHeader      = ErrPack{4003, "input header error"}
	ErrInputBody        = ErrPack{4004, "input body error"}
	ErrParseToken       = ErrPack{5201, "parse token error"}
	ErrServiceConn      = ErrPack{5301, "service communication error"}
	ErrLogic            = ErrPack{5501, "logical error"}
	ErrCacheConn        = ErrPack{5601, "cache connection error"}
	ErrNoCache          = ErrPack{5602, "no cache error"}
	ErrDBConn           = ErrPack{5701, "database connection error"}
	ErrNoRecord         = ErrPack{5702, "database no record error"}
	ErrDuplicatedRecord = ErrPack{5703, "database duplicated record error"}
	ErrTypeConv         = ErrPack{5901, "type conversion error"}
	ErrGenJWT           = ErrPack{5903, "generate JWT error"}
	ErrParseJWT         = ErrPack{5903, "parse JWT error"}
)

Functions

This section is empty.

Types

type ErrPack

type ErrPack struct {
	Code int32  `json:"code,omitempty" ep:"err.code"`
	Msg  string `json:"msg,omitempty" ep:"err.msg"`
}

func (ErrPack) Error

func (e ErrPack) Error() string

Error implement error type

type Packer

type Packer struct {
	V interface{}
}

func (*Packer) Pack

func (p *Packer) Pack(err error) interface{}

Pack return the given interface with tagged values and ErrPack

func (*Packer) PackWithError

func (p *Packer) PackWithError(err error) interface{}

PackWithError will do the pack and additionally log the error with Error level

func (*Packer) PackWithInfo

func (p *Packer) PackWithInfo(err error) interface{}

PackWithInfo will do the pack and additionally log the error with INFO level

func (*Packer) PackWithWarn

func (p *Packer) PackWithWarn(err error) interface{}

PackWithWarn will do the pack and additionally log the error with WARN level

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL