optimize pkg codes

This commit is contained in:
zhuyasen
2022-11-11 22:58:11 +08:00
parent 36dcda16ba
commit b8c59f25f9
17 changed files with 149 additions and 92 deletions

View File

@@ -72,7 +72,7 @@ func (a *App) watch(ctx context.Context) error {
_ = a.stop()
return ctx.Err()
case s := <-quit: // system notification signal
fmt.Printf("receive a quit signal: %s\n", s.String())
fmt.Printf("quit signal: %s\n", s.String())
if err := a.stop(); err != nil {
return err
}

View File

@@ -1,13 +1,13 @@
## errcode
错误码通常包括系统级错误码和服务级错误码,一共6位十进制数字组成例如200101
错误码通常包括系统级错误码和服务级错误码,一共5位十进制数字组成例如20101
| 前两位数字 | 中间两位数字 | 最后两位数字 |
|:------------------------------|:-------|:-------|
| 对于http错误码20表示服务级错误(10为系统级错误) | 服务模块代码 | 具体错误代码 |
| 对于grpc错误码40表示服务级错误(30为系统级错误) | 服务模块代码 | 具体错误代码 |
| 第一位数字 | 中间两位数字 | 最后两位数字 |
|:----------------------------|:-------|:-------|
| 对于http错误码2表示服务级错误(1为系统级错误) | 服务模块代码 | 具体错误代码 |
| 对于grpc错误码4表示服务级错误(3为系统级错误) | 服务模块代码 | 具体错误代码 |
- 错误级别占2位数10(http)和30(grpc)表示系统级错误20(http)和40(grpc)表示服务级错误,通常是由用户非法操作引起的。
- 错误级别占位数1(http)和3(grpc)表示系统级错误2(http)和4(grpc)表示服务级错误,通常是由用户非法操作引起的。
- 服务模块占两位数:一个大型系统的服务模块通常不超过两位数,如果超过,说明这个系统该拆分了。
- 错误码占两位数:防止一个模块定制过多的错误码,后期不好维护。
@@ -19,7 +19,7 @@
```go
// 定义错误码
var ErrLogin = errcode.NewError(200101, "用户名或密码错误")
var ErrLogin = errcode.NewError(20101, "用户名或密码错误")
// 请求返回
response.Error(c, errcode.LoginErr)
@@ -31,7 +31,7 @@
```go
// 定义错误码
var ErrLogin = NewRPCStatus(400101, "用户名或密码错误")
var ErrLogin = NewRPCStatus(40101, "用户名或密码错误")
// 返回错误
errcode.ErrLogin.Err()

View File

@@ -9,17 +9,14 @@ import (
var errCodes = map[int]*Error{}
// Error 错误
// Error error
type Error struct {
// 错误码
code int
// 错误消息
msg string
// 详细信息
code int
msg string
details []string
}
// NewError 创建新错误信息
// NewError create a new error message
func NewError(code int, msg string) *Error {
if v, ok := errCodes[code]; ok {
panic(fmt.Sprintf("http error code = %d already exists, please replace with a new error code, old msg = %s", code, v.Msg()))
@@ -29,7 +26,7 @@ func NewError(code int, msg string) *Error {
return e
}
// Err 转为标准error
// Err covert to standard error
func (e *Error) Err() error {
if len(e.details) == 0 {
return fmt.Errorf("code = %d, msg = %s", e.code, e.msg)
@@ -37,27 +34,22 @@ func (e *Error) Err() error {
return fmt.Errorf("code = %d, msg = %s, details = %v", e.code, e.msg, e.details)
}
// Code 错误码
// Code get error code
func (e *Error) Code() int {
return e.code
}
// Msg 错误信息
// Msg get error code message
func (e *Error) Msg() string {
return e.msg
}
// Msgf 附加信息
func (e *Error) Msgf(args []interface{}) string {
return fmt.Sprintf(e.msg, args...)
}
// Details 错误详情
// Details get error code details
func (e *Error) Details() []string {
return e.details
}
// WithDetails 携带附加错误详情
// WithDetails add error details
func (e *Error) WithDetails(details ...string) *Error {
newError := *e
newError.details = []string{}
@@ -66,7 +58,7 @@ func (e *Error) WithDetails(details ...string) *Error {
return &newError
}
// ToHTTPCode 转换为http错误码
// ToHTTPCode convert to http error code
func (e *Error) ToHTTPCode() int {
switch e.Code() {
case Success.Code():
@@ -83,6 +75,8 @@ func (e *Error) ToHTTPCode() int {
return http.StatusForbidden
case NotFound.Code():
return http.StatusNotFound
case AlreadyExists.Code():
return http.StatusConflict
case Timeout.Code():
return http.StatusRequestTimeout
}
@@ -90,7 +84,7 @@ func (e *Error) ToHTTPCode() int {
return e.Code()
}
// ParseError 根据标准错误信息解析出错误码和错误信息
// ParseError parsing out error codes from error messages
func ParseError(err error) *Error {
if err == nil {
return Success

View File

@@ -8,14 +8,13 @@ import (
)
func TestNewError(t *testing.T) {
code := 101
code := 21101
msg := "something is wrong"
e := NewError(code, msg)
assert.Equal(t, code, e.Code())
assert.Equal(t, msg, e.Msg())
assert.Contains(t, e.Err().Error(), msg)
assert.Contains(t, e.Msgf([]interface{}{"foo", "bar"}), msg)
details := []string{"a", "b", "c"}
assert.Equal(t, details, e.WithDetails(details...).Details())
@@ -63,5 +62,5 @@ func TestHCode(t *testing.T) {
defer func() {
recover()
}()
code = HCode(10001)
code = HCode(101)
}

View File

@@ -1,18 +1,18 @@
package errcode
// nolint
// 服务级别错误码有Err前缀
var (
// ErrUserCreate = NewError(HCode(1)+1, "创建用户失败") // 200101
// ErrUserDelete = NewError(HCode(1)+2, "删除用户失败") // 200102
// ErrUserUpdate = NewError(HCode(1)+3, "更新用户失败") // 200103
// ErrUserGet = NewError(HCode(1)+4, "获取用户失败") // 200104
)
// HCode 根据编号生成200000~300000之间的错误码
// HCode Generate an error code between 20000 and 30000 according to the number
//
// http service level error code, Err prefix, example.
//
// var (
// ErrUserCreate = NewError(HCode(1)+1, "failed to create user") // 200101
// ErrUserDelete = NewError(HCode(1)+2, "failed to delete user") // 200102
// ErrUserUpdate = NewError(HCode(1)+3, "failed to update user") // 200103
// ErrUserGet = NewError(HCode(1)+4, "failed to get user details") // 200104
// )
func HCode(NO int) int {
if NO > 1000 {
panic("NO must be < 1000")
if NO > 99 || NO < 1 {
panic("NO range must be between 0 to 100")
}
return 200000 + NO*100
}

View File

@@ -1,21 +1,20 @@
package errcode
// nolint
// http系统级别错误码无Err前缀
// http system level error code, error code range 10000~20000
var (
Success = NewError(0, "ok")
InvalidParams = NewError(100001, "参数错误")
Unauthorized = NewError(100002, "认证错误")
InternalServerError = NewError(100003, "服务内部错误")
NotFound = NewError(100004, "资源不存在")
AlreadyExists = NewError(100005, "资源已存在")
Timeout = NewError(100006, "超时")
TooManyRequests = NewError(100007, "请求过多")
Forbidden = NewError(100008, "拒绝访问")
LimitExceed = NewError(100009, "访问限制")
DeadlineExceeded = NewError(100010, "已超过最后期限")
AccessDenied = NewError(100011, "拒绝访问")
MethodNotAllowed = NewError(100012, "不允许使用的方法")
MethodServiceUnavailable = NewError(100013, "服务不可用")
InvalidParams = NewError(10001, "Invalid Parameter")
Unauthorized = NewError(10002, "Unauthorized")
InternalServerError = NewError(10003, "Internal Server Error")
NotFound = NewError(10004, "Not Found")
AlreadyExists = NewError(10005, "Conflict")
Timeout = NewError(10006, "Request Timeout")
TooManyRequests = NewError(10007, "Too Many Requests")
Forbidden = NewError(10008, "Forbidden")
LimitExceed = NewError(10009, "Limit Exceed")
DeadlineExceeded = NewError(10010, "Deadline Exceeded")
AccessDenied = NewError(10011, "Access Denied")
MethodNotAllowed = NewError(10012, "Method Not Allowed")
ServiceUnavailable = NewError(10013, "Service Unavailable")
)

View File

@@ -104,7 +104,7 @@ func ToHTTPErr(st *status.Status) *Error {
case StatusMethodNotAllowed.status.Code():
return MethodNotAllowed
case StatusServiceUnavailable.status.Code():
return MethodServiceUnavailable
return ServiceUnavailable
}
return &Error{

View File

@@ -8,14 +8,14 @@ import (
"google.golang.org/grpc/status"
)
// RPCStatus grpc 状态
// RPCStatus rpc status
type RPCStatus struct {
status *status.Status
}
var statusCodes = map[codes.Code]string{}
// NewRPCStatus 新建一个status
// NewRPCStatus create a new rpc status
func NewRPCStatus(code codes.Code, msg string) *RPCStatus {
if v, ok := statusCodes[code]; ok {
panic(fmt.Sprintf("grpc status code = %d already exists, please replace with a new error code, old msg = %s", code, v))

View File

@@ -13,8 +13,8 @@ import "google.golang.org/grpc/codes"
// StatusUserGet = NewRPCStatus(RCode(1)+4, "failed to get user details") // 40104
// )
func RCode(NO int) codes.Code {
if NO > 99 {
panic("NO must be < 100")
if NO > 99 || NO < 1 {
panic("NO range must be between 0 to 100")
}
return codes.Code(40000 + NO*100)
}

View File

@@ -1,22 +1,21 @@
package errcode
// nolint
// rpc系统级别错误码有status前缀
// rpc system level error code with status prefix, error code range 30000~40000
var (
StatusSuccess = NewRPCStatus(0, "ok")
StatusInvalidParams = NewRPCStatus(300001, "参数错误")
StatusUnauthorized = NewRPCStatus(300002, "认证错误")
StatusInternalServerError = NewRPCStatus(300003, "服务内部错误")
StatusNotFound = NewRPCStatus(300004, "资源不存在")
StatusAlreadyExists = NewRPCStatus(300005, "资源已存在")
StatusTimeout = NewRPCStatus(300006, "访问超时")
StatusTooManyRequests = NewRPCStatus(300007, "请求过多")
StatusForbidden = NewRPCStatus(300008, "拒绝访问")
StatusLimitExceed = NewRPCStatus(300009, "访问限制")
StatusDeadlineExceeded = NewRPCStatus(300010, "已超过最后期限")
StatusAccessDenied = NewRPCStatus(300011, "拒绝访问")
StatusMethodNotAllowed = NewRPCStatus(300012, "不允许使用的方法")
StatusServiceUnavailable = NewRPCStatus(300013, "服务不可用")
StatusInvalidParams = NewRPCStatus(30001, "Invalid Parameter")
StatusUnauthorized = NewRPCStatus(30002, "Unauthorized")
StatusInternalServerError = NewRPCStatus(30003, "Internal Server Error")
StatusNotFound = NewRPCStatus(30004, "Not Found")
StatusAlreadyExists = NewRPCStatus(30005, "Conflict")
StatusTimeout = NewRPCStatus(30006, "Request Timeout")
StatusTooManyRequests = NewRPCStatus(30007, "Too Many Requests")
StatusForbidden = NewRPCStatus(30008, "Forbidden")
StatusLimitExceed = NewRPCStatus(30009, "Limit Exceed")
StatusDeadlineExceeded = NewRPCStatus(30010, "Deadline Exceeded")
StatusAccessDenied = NewRPCStatus(30011, "Access Denied")
StatusMethodNotAllowed = NewRPCStatus(30012, "Method Not Allowed")
StatusServiceUnavailable = NewRPCStatus(30013, "Service Unavailable")
)

View File

@@ -83,7 +83,7 @@ func Output(c *gin.Context, code int, msg ...interface{}) {
case http.StatusTooManyRequests:
respJSONWithStatusCode(c, http.StatusTooManyRequests, errcode.LimitExceed.Msg(), msg...)
case http.StatusServiceUnavailable:
respJSONWithStatusCode(c, http.StatusServiceUnavailable, errcode.MethodServiceUnavailable.Msg(), msg...)
respJSONWithStatusCode(c, http.StatusServiceUnavailable, errcode.ServiceUnavailable.Msg(), msg...)
default:
respJSONWithStatusCode(c, code, http.StatusText(code), msg...)

View File

@@ -2,6 +2,7 @@ package gofile
import (
"os"
"path"
"path/filepath"
"runtime"
"strings"
@@ -94,6 +95,30 @@ func ListDirsAndFiles(dirPath string) (map[string][]string, error) {
return df, nil
}
// FuzzyMatchFiles 模糊匹配文件,只匹配*号
func FuzzyMatchFiles(f string) []string {
var files []string
dir, filenameReg := filepath.Split(f)
if !strings.Contains(filenameReg, "*") {
files = append(files, f)
return files
}
lFiles, err := ListFiles(dir)
if err != nil {
return files
}
for _, file := range lFiles {
_, filename := filepath.Split(file)
isMatch, _ := path.Match(filenameReg, filename)
if isMatch {
files = append(files, file)
}
}
return files
}
// 带过滤条件通过迭代方式遍历文件
func walkDirWithFilter(dirPath string, allFiles *[]string, filter filterFn) error {
files, err := os.ReadDir(dirPath)

View File

@@ -111,3 +111,11 @@ func TestErrorPath(t *testing.T) {
err = walkDir2(dir, nil, nil)
assert.Error(t, err)
}
func TestFuzzyMatchFiles(t *testing.T) {
files := FuzzyMatchFiles("./README.md")
assert.Equal(t, 1, len(files))
files = FuzzyMatchFiles("./*_test.go")
assert.Equal(t, 2, len(files))
}

View File

@@ -17,9 +17,9 @@ var _ Replacer = (*replacerInfo)(nil)
// Replacer 接口
type Replacer interface {
SetReplacementFields(fields []Field)
SetIgnoreFiles(filenames ...string)
SetSubDirsAndFiles(subDirs []string, subFiles ...string)
SetIgnoreSubDirs(dirs ...string)
SetSubDirs(subDirs ...string)
SetIgnoreSubFiles(filenames ...string)
SetOutputDir(absDir string, name ...string) error
GetOutputDir() string
GetSourcePath() string
@@ -100,13 +100,14 @@ func (r *replacerInfo) SetReplacementFields(fields []Field) {
r.replacementFields = newFields
}
// SetSubDirs 设置处理指定子目录,其他目录下文件忽略处理
func (r *replacerInfo) SetSubDirs(subDirs ...string) {
// SetSubDirsAndFiles 设置处理指定子目录,其他目录下文件忽略处理
func (r *replacerInfo) SetSubDirsAndFiles(subDirs []string, subFiles ...string) {
if len(subDirs) == 0 {
return
}
subDirs = r.covertPathsDelimiter(subDirs...)
subFiles = r.covertPathsDelimiter(subFiles...)
var files []string
isExistFile := make(map[string]struct{})
@@ -122,6 +123,17 @@ func (r *replacerInfo) SetSubDirs(subDirs ...string) {
files = append(files, file)
}
}
for _, sf := range subFiles {
if isMatchFile(file, sf) {
// 避免重复文件
if _, ok := isExistFile[file]; ok {
continue
} else {
isExistFile[file] = struct{}{}
}
files = append(files, file)
}
}
}
if len(files) == 0 {
@@ -131,7 +143,7 @@ func (r *replacerInfo) SetSubDirs(subDirs ...string) {
}
// SetIgnoreFiles 设置忽略处理的文件
func (r *replacerInfo) SetIgnoreFiles(filenames ...string) {
func (r *replacerInfo) SetIgnoreSubFiles(filenames ...string) {
r.ignoreFiles = append(r.ignoreFiles, filenames...)
}
@@ -267,12 +279,16 @@ func (r *replacerInfo) SaveFiles() error {
func (r *replacerInfo) isIgnoreFile(file string) bool {
isIgnore := false
_, filename := filepath.Split(file)
//_, filename := filepath.Split(file)
for _, v := range r.ignoreFiles {
if filename == v {
if isMatchFile(file, v) {
isIgnore = true
break
}
//if filename == v {
// isIgnore = true
// break
//}
}
return isIgnore
}
@@ -384,3 +400,17 @@ func isSubPath(filePath string, subPath string) bool {
dir, _ := filepath.Split(filePath)
return strings.Contains(dir, subPath)
}
func isMatchFile(filePath string, sf string) bool {
dir1, file1 := filepath.Split(filePath)
dir2, file2 := filepath.Split(sf)
if file1 != file2 {
return false
}
l1, l2 := len(dir1), len(dir2)
if l1 >= l2 && dir1[l1-l2:] == dir2 {
return true
}
return false
}

View File

@@ -56,6 +56,7 @@ func TestNewWithFS(t *testing.T) {
r := tt.args.fn()
subDirs := []string{"testDir/replace"}
subFiles := []string{"testDir/foo.txt"}
ignoreDirs := []string{"testDir/ignore"}
ignoreFiles := []string{"test.txt"}
fields := []Field{
@@ -69,10 +70,10 @@ func TestNewWithFS(t *testing.T) {
IsCaseSensitive: true,
},
}
r.SetSubDirs(subDirs...) // 只处理指定子目录,为空时表示指定全部文件
r.SetIgnoreFiles(ignoreDirs...) // 忽略替换目录
r.SetIgnoreFiles(ignoreFiles...) // 忽略替换文件
r.SetReplacementFields(fields) // 设置替换文本
r.SetSubDirsAndFiles(subDirs, subFiles...) // 只处理指定子目录
r.SetIgnoreSubDirs(ignoreDirs...) // 忽略处理子目录
r.SetIgnoreSubFiles(ignoreFiles...) // 忽略处理目录下的文件
r.SetReplacementFields(fields) // 设置替换文本
_ = r.SetOutputDir(fmt.Sprintf("%s/replacer_test/%s_%s",
os.TempDir(), tt.name, time.Now().Format("150405"))) // 设置输出目录和名称
_, err := r.ReadFile("replace.txt")
@@ -95,8 +96,8 @@ func TestReplacerError(t *testing.T) {
r, err := New("testDir")
assert.NoError(t, err)
r.SetIgnoreFiles()
r.SetSubDirs()
r.SetIgnoreSubFiles()
r.SetSubDirsAndFiles(nil)
err = r.SetOutputDir("/tmp/yourServerName")
assert.NoError(t, err)
path := r.GetSourcePath()

View File

@@ -0,0 +1 @@
123

View File

@@ -0,0 +1 @@
456