当前位置:网站首页>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
边栏推荐
- 【Hot100】20. 有效的括号
- 【Hot100】20. Valid parentheses
- 2023 spring recruitment Internship - personal interview process and face-to-face experience sharing
- 动作捕捉系统用于苹果采摘机器人
- 怎么用MySQL语言进行行列装置?
- IM即时通讯开发实现心跳保活遇到的问题
- Submission lottery - light application server essay solicitation activity (may) award announcement
- 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
- 表格存储中tablestore 目前支持mysql哪些函数呢?
- 程序员职业生涯真的很短吗?
猜你喜欢
MLPerf Training v2.0 榜单发布,在同等GPU配置下百度飞桨性能世界第一
ThinkPHP kernel work order system source code commercial open source version multi user + multi customer service + SMS + email notification
Nuxt. JS data prefetching
复杂度相关OJ题(LeetCode、C语言、复杂度、消失的数字、旋转数组)
2023届春招实习-个人面试过程和面经分享
How to adjust the size of computer photos to what you want
EndeavourOS移动硬盘安装
【LeetCode】43. String multiplication
Idea start command line is too long problem handling
There is a difference between u-standard contract and currency standard contract. Will u-standard contract explode
随机推荐
The picgo shortcut is amazing. This person thinks exactly the same as me
Go 语言源码级调试器 Delve
EndeavourOS移动硬盘安装
Comprehensively view the value of enterprise digital transformation
vim用户自动命令示例
Please, stop painting star! This has nothing to do with patriotism!
There will be a gap bug when the search box and button are zoomed
如何使用phpIPAM来管理IP地址和子网
德国iF多项大奖加冕,这副耳机有多强?音珀GTW 270 Hybrid深度评测
StoneDB 为国产数据库添砖加瓦,基于 MySQL 的一体化实时 HTAP 数据库正式开源!
Stonedb is building blocks for domestic databases, and the integrated real-time HTAP database based on MySQL is officially open source!
Nuxt.js数据预取
[daily news]what happened to the corresponding author of latex
运动捕捉系统原理
制造业数字化转型究竟是什么
怎麼用MySQL語言進行行列裝置?
SQLServer查询: a.id与b.id相同时,a.id对应的a.p在b.id对应的b.p里找不到的话,就显示出这个a.id和a.p
复杂度相关OJ题(LeetCode、C语言、复杂度、消失的数字、旋转数组)
When ABAP screen switching, refresh the previous screen
Huawei issued hcsp-solution-5g security talent certification to help build 5g security talent ecosystem