当前位置:网站首页>Why is the pkg/errors tripartite library more recommended for go language error handling?
Why is the pkg/errors tripartite library more recommended for go language error handling?
2022-07-01 16:21:00 【frank.】
Hello everyone , I am a frank.
01
Introduce
Go Language project development , We usually need to deal with errors in code logic ,Go Official standard library errors It provides us with some methods , such as New,Unwarp,Is and As.
among , What we use most is New, however , In our reality Go Project under development , Will use some layered design , such as MVC,Clean Architecture etc. .
In projects that use hierarchical design , If we use Go Standard library errors Wrong definition , You will encounter the problem of error coverage .
02
About the standard library errors Error coverage problem
Go Standard library errors Of New Method , Only a simple error message can be defined , In the project code of hierarchical design , You will encounter the problem of error coverage , For example, our sample project code , It uses Clean Architecture Layered design .
Project hierarchical directory :
.
├── app
│ └── main.go
├── domain
│ └── user.go
├── go.mod
├── go.sum
└── user
├── delivery
│ └── http
│ └── user.go
├── repository
│ └── mysql
│ └── user.go
└── usecase
└── user.go
In the example project , So let's use Go Standard library errors Of New Method definition error , The code snippet is as follows :
repository layer :
func (m *mysqlUserRepository) GetUserById(ctx context.Context, user *domain.User) (err error) {
_, err = m.DB.Get(user)
fmt.Printf("mysqlUserRepository || GetUserById() || uid=%v || err=%v\n", user.Id, err)
return
}
usecase layer :
func (u *userUsecase) GetUserById(ctx context.Context, user *domain.User) (err error) {
if user.Id == 0 {
err = errors.New("invalid request parameter")
}
err = u.userRepo.GetUserById(ctx, user)
fmt.Printf("userUsecase || GetUserById() || uid=%v || err=%v\n", user.Id, err)
return
}
delivery layer :
func (u *UserHandler) GetUserById(c echo.Context) error {
idP, err := strconv.Atoi(c.Param("id"))
if err != nil {
return c.JSON(http.StatusNotFound, err)
}
id := int64(idP)
ctx := c.Request().Context()
user := &domain.User{
Id: id,
}
err = u.UserUsecase.GetUserById(ctx, user)
if err != nil {
err = errors.New("UserUsecase error")
fmt.Printf("UserHandler || GetUserById() || uid=%v || err=%+v\n", id, err)
return c.JSON(http.StatusInternalServerError, err)
}
return c.JSON(http.StatusOK, user)
}
Read the above three pieces of code , We can find out , We have error handling code in each layer , We deliberately use the wrong request parameters , And write the password of the database connection incorrectly , The error that triggered the application .
Output results :
mysqlUserRepository || GetUserById() || uid=1 || err=Error 1045: Access denied for user 'root'@'172.17.0.1' (using password: YES)
userUsecase || GetUserById() || uid=1 || err=Error 1045: Access denied for user 'root'@'172.17.0.1' (using password: YES)
UserHandler || GetUserById() || uid=1 || err=UserUsecase error
Read the output , We can find out ,usecase Layer definition error , The called repository Layer returns error coverage ;delivery Layer definition errors will usecase Error coverage returned by layer .
Because we printed errors on each layer , Check carefully , You can still locate the error , But it's still complicated , Not only do printing errors at each level make the code less elegant , And it can't quickly locate the error .
How to solve this problem ? Use a tripartite Library github.com/pkg/errors Replace Go Standard library errors.
03
Three party Library pkg/errors
Use a tripartite Library pkg/errors It can solve the problem that the error information of call stack overlaps each other in the project of hierarchical design , It can output wrong stack information for us , New error messages can be added to the existing error messages , So as to solve the problem that the output error information lacks context .
So let's revise that Part 02 Example code for , take Go Standard library errors Replace with a third-party library pkg/errors, I believe careful readers have found , Because the names of these two bags are the same , And they all have New Method , So it's convenient to replace , Just replace the imported package .
Sample code :
import (
// "errors"
"fmt"
"github.com/labstack/echo/v4"
"github.com/pkg/errors"
"github.com/weirubo/learn_go/lesson41/domain"
"net/http"
"strconv"
)
Output result after replacement :
mysqlUserRepository || GetUserById() || uid=0 || err=Error 1045: Access denied for user 'root'@'172.17.0.1' (using password: YES)
userUsecase || GetUserById() || uid=0 || err=Error 1045: Access denied for user 'root'@'172.17.0.1' (using password: YES)
UserHandler || GetUserById() || uid=0 || err=UserUsecase error
github.com/weirubo/learn_go/lesson41/user/delivery/http.(*UserHandler).GetUserById
/Users/frank/GolandProjects/learn_go/lesson41/user/delivery/http/user.go:36
github.com/labstack/echo/v4.(*Echo).add.func1
/Users/frank/go/pkg/mod/github.com/labstack/echo/[email protected]/echo.go:520
github.com/labstack/echo/v4.(*Echo).ServeHTTP
/Users/frank/go/pkg/mod/github.com/labstack/echo/[email protected]/echo.go:630
net/http.serverHandler.ServeHTTP
/usr/local/go/src/net/http/server.go:2916
net/http.(*conn).serve
/usr/local/go/src/net/http/server.go:1966
runtime.goexit
/usr/local/go/src/runtime/asm_amd64.s:1571
Read the output above , We can find that the error handling package consists of Go Standard library errors Replace with a third-party library pkg/errors after , The output results are not only Go Standard library errors Error messages for , Wrong stack information is also output .
So far, , We just switched the imported package , The error message contains the wrong stack information , however , Our error coverage problem has not been solved , We also need to use third-party libraries pkg/errors Of Wrap Method , Let's change the code again , take New Replace the method with Wrap Method .
delivery layer :
...
if err != nil {
// err = errors.New("UserUsecase error")
err = errors.Wrap(err, "UserUsecase error")
fmt.Printf("UserHandler || GetUserById() || uid=%v || err=%+v\n", id, err)
return c.JSON(http.StatusInternalServerError, err)
}
...
Read the code above , We modify delivery Layer error handling code , take New Replace the method with Wrap Method , It can be based on the existing error information , Attach new error information and wrong stack information .
Output results :
mysqlUserRepository || GetUserById() || uid=0 || err=Error 1045: Access denied for user 'root'@'172.17.0.1' (using password: YES)
userUsecase || GetUserById() || uid=0 || err=Error 1045: Access denied for user 'root'@'172.17.0.1' (using password: YES)
UserHandler || GetUserById() || uid=0 || err=Error 1045: Access denied for user 'root'@'172.17.0.1' (using password: YES)
UserUsecase error
github.com/weirubo/learn_go/lesson41/user/delivery/http.(*UserHandler).GetUserById
/Users/frank/GolandProjects/learn_go/lesson41/user/delivery/http/user.go:37
github.com/labstack/echo/v4.(*Echo).add.func1
/Users/frank/go/pkg/mod/github.com/labstack/echo/[email protected]/echo.go:520
github.com/labstack/echo/v4.(*Echo).ServeHTTP
/Users/frank/go/pkg/mod/github.com/labstack/echo/[email protected]/echo.go:630
net/http.serverHandler.ServeHTTP
/usr/local/go/src/net/http/server.go:2916
net/http.(*conn).serve
/usr/local/go/src/net/http/server.go:1966
runtime.goexit
/usr/local/go/src/runtime/asm_amd64.s:1571
Read the above output , We can find it in delivery Error message defined by layer , No more override calls usecase The error message returned by the layer method , Both are output normally .
It should be noted that , Output error information and stack information at the same time , Placeholders need to use %+v, Don't output stack information at every layer , This will repeatedly print stack information , Usually, if the stack information is printed on the lower layer , Don't print stack information on the upper layer .
Besides , Three party Library pkg/errors The other two methods WithMessage and WithStack It's also more commonly used , They are based on the existing error messages , Attach new error information and wrong stack information , We are in the actual project development , You can choose to use the appropriate method as needed .
04
summary
In this article, we talked about using Go Standard library errors Limitations and deficiencies of error handling , In order to solve its shortcomings , We introduced the use of third-party libraries pkg/errors Replace Go Standard library errors, And third-party library pkg/errors How to use several common methods of .
About the third-party library pkg/errors More ways , Interested readers can read the document to learn how to use .
Reference material :
- https://pkg.go.dev/github.com/pkg/[email protected]
- https://pkg.go.dev/errors
- https://dave.cheney.net/2016/06/12/stack-traces-and-the-errors-package
- https://morioh.com/p/777d15fe7828
边栏推荐
- 超视频时代,什么样的技术会成为底座?
- 投稿开奖丨轻量应用服务器征文活动(5月)奖励公布
- Solution to the problem that the keypad light does not light up when starting up
- Guide for high-end programmers to fish at work
- SQLServer查询: a.id与b.id相同时,a.id对应的a.p在b.id对应的b.p里找不到的话,就显示出这个a.id和a.p
- When ABAP screen switching, refresh the previous screen
- UML tourism management system "suggestions collection"
- 红队第10篇:coldfusion反序列化过waf改exp拿靶标的艰难过程
- [SQL statement] Why do you select two Shanghai and query different counts here? I want it to become a Shanghai, and count only displays a sum
- 复杂度相关OJ题(LeetCode、C语言、复杂度、消失的数字、旋转数组)
猜你喜欢

The sharp drop in electricity consumption in Guangdong shows that the substitution of high-tech industries for high-energy consumption industries has achieved preliminary results
![[open source data] open source data set for cross modal (MRI, Meg, eye movement) human spatial memory research based on virtual reality scenes](/img/73/98e4847783be26d86d147425ce3ecd.jpg)
[open source data] open source data set for cross modal (MRI, Meg, eye movement) human spatial memory research based on virtual reality scenes

Sqlserver query: when a.id is the same as b.id, and the A.P corresponding to a.id cannot be found in the B.P corresponding to b.id, the a.id and A.P will be displayed

程序员职业生涯真的很短吗?

Nuxt. JS data prefetching

数据库系统原理与应用教程(006)—— 编译安装 MySQL5.7(Linux 环境)

The supply of chips has turned to excess, and the daily output of Chinese chips has increased to 1billion, which will make it more difficult for foreign chips
![[daily news]what happened to the corresponding author of latex](/img/0f/d19b27dc42124c89993dee1bada838.png)
[daily news]what happened to the corresponding author of latex

There will be a gap bug when the search box and button are zoomed

How does win11 set user permissions? Win11 method of setting user permissions
随机推荐
ABAP call restful API
Uncover the "intelligence tax" of mousse: spend 4billion on marketing, and only 7 invention patents
OJ questions related to complexity (leetcode, C language, complexity, vanishing numbers, rotating array)
IM即时通讯开发实现心跳保活遇到的问题
Huawei issued hcsp-solution-5g security talent certification to help build 5g security talent ecosystem
实现数字永生还有多久?元宇宙全息真人分身#8i
【SQL语句】请问这边为什么select出了两个上海,查询出了不同的count我想让他变成一个上海,count只显示一个总和
Analysis of PostgreSQL storage structure
Im instant messaging develops a message delivery scheme for 10000 people
How to use MySQL language for row and column devices?
Go language learning notes - Gorm use - table addition, deletion, modification and query | web framework gin (VIII)
圈铁发音,动感与无噪强强出彩,魔浪HIFIair蓝牙耳机测评
Pico, do you want to save or bring consumer VR?
Problems encountered in IM instant messaging development to maintain heartbeat
Red team Chapter 8: blind guess the difficult utilization process of the package to upload vulnerabilities
Win11如何設置用戶權限?Win11設置用戶權限的方法
Solution to the problem that the keypad light does not light up when starting up
Smart Party Building: faith through time and space | 7.1 dedication
Microservice tracking SQL (support Gorm query tracking under isto control)
Comment win11 définit - il les permissions de l'utilisateur? Win11 comment définir les permissions de l'utilisateur