有这样一个场景, 我们在e这个包下, 有一个err_code.go文件,在其中自定义了一个错误码结构体和一些错误码,内容如下:

1
2
3
4
5
6
7
8
9
10
11
package e

type ErrCode struct {
Code int
Msg string
}
var (
Success = ErrCode{Code: 10000, Msg: ""}
UnknownErr = ErrCode{Code: 10001, Msg: "未知错误"}
InvalidParams = ErrCode{Code: 10002, Msg: "参数不合法"}
)

现在我们想获取到所有这些预先定义的错误码的code,应该如何做呢?

可以借助go标准库中AST语法树的能力遍历所有变量,然后过滤得到我们想要的变量类型, 具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
func Test_IntlDictMatchErrCodeEnum(t *testing.T) {
fset := token.NewFileSet()
// 此处填写错误码所处包的相对路径
pkgs, err := parser.ParseDir(fset, "../pkg/e", nil, parser.ParseComments)
if err != nil {
log.Fatal(err)
}
// 此处填写实际包的名字
pkg := pkgs["e"]

// 遍历文件
for _, file := range pkg.Files {
// 遍历文件的声明
for _, decl := range file.Decls {
// 检查声明是否是变量声明
if genDecl, ok := decl.(*ast.GenDecl); ok && genDecl.Tok == token.VAR {
// 遍历变量声明的规范
for _, spec := range genDecl.Specs {
if valueSpec, ok := spec.(*ast.ValueSpec); ok {
codeElt := valueSpec.Values[0]
if y, ok := codeElt.(*ast.CompositeLit); ok {
if j, ok := y.Elts[0].(*ast.KeyValueExpr); ok {
if l, ok := j.Value.(*ast.BasicLit); ok {
// 此处能获取到错误码对应的Code
fmt.Printf("code:%s\n", l.Value)
}
}
}
}
}
}
}
}
}