写在前面
在公司开发业务过程中发现经常需要引用外部资源,包括外部服务rpc、http、rocketmq,还有外部依赖包log、error、common等,在代码各个模块、各个文件里面直接引用,这有什么问题呢?
- 需要替换某个包的时候需要修改所有引用的地方。之前在项目中引用excelize包的时候发现有个bug,因此需要替换这个包,发现需要改很多文件。
- 不知道外部依赖能提供哪些接口。如果直接在需要用rpc的地方直接使用client,需要引入相关的requst和response的定义,并且根本不摘除client提供了哪些方法,需要查看proto。最坑的是如果client修改了某个接口的定义,所有调用的地方都需要修改,包括单测。这个改动可能仅仅是某个场景需要而加的,但是导致其他所有场景都需要改这个接口,显然不合理。
- 业务代码到处引入外部依赖包。
- 当需要对某个接口做统一处理的时候无法实现。比如想对某个rpc调用统计耗时,需要在每个调用的地方加上相关代码,太恶心。
解决方法:将外部资源封装一层
将当前服务引入的外部资源放在一个目录下,并且通过定义好接口,封装一层
pkg
├── error
│ └── error.go
├── excel
│ └── excel.go
├── rocketmq
│ └── rocketmq.go
└── rpc
├── service1.go
└── service2.go
error/error.go文件如下:
package error
import (
"github.com/pkg/errors"
)
type Error interface {
Errorf(format string, args ...interface{}) error
Wrapf(err error, format string, args ...interface{}) error
}
func New() Error {
return &innerError{}
}
type innerError struct {
// err error
}
func (i *innerError) Errorf(format string, args ...interface{}) error {
// TODO:可以做一些本服务相关的事情,比如报警、保存、添加服务、用户相关信息到error中
return errors.Errorf(format, args...)
}
func (i *innerError) Wrapf(err error, format string, args ...interface{}) error {
return errors.Wrapf(err, format, args...)
}
在其他业务文件中只要引入pkg/error
包就行了,无需关心github.com/pkg/errors
包
总结
本文纯属个人观点和习惯,肯定有人会觉得多此一举,因为在代码review的时候就有同事提出来没有必要,觉得直接在用到的地方直接引用github.com/pkg/errors
就行了。有不同意见可留言探讨,一起学习。
每天学习一个知识点,必定会有质变!