UP | HOME

解析go源文件得到常量的值

Table of Contents

1 问题描述

我需要一个能够手动解析.go文件程序,获取其中定义的常量的值和之后的注释。这个需求还是很常见的,例如在项目中常把errcode定义为常量,然后需要根据注释解析成errmsg给前端用。但是对于go来说我们不能使用一般的正则来干这件事情,因为在go中iota使用的地方很多,如果要解析得到常量的值的话,用正则太过麻烦。恰好go提供了解析.go文件的包,例如: go/token, go/ast, go/parse等。详细情况可以见:,经过半天折腾,终于完满解决此问题。现在记录在此,不过go的这些包有很多干货啊,以后再深入研究。

2 实际代码

package main

import (
    "fmt"
    "go/ast"
    "go/importer"
    "go/parser"
    "go/token"
    "go/types"
    "reflect"
)

func main() {
    m, _ := ParseFile("./errcode.go")
    fmt.Printf("%#v", m)
}

func ParseFile(fileName string) (map[string]string, error) {
    fset := token.NewFileSet()
  // 解析文件,主要解析token
    f, err := parser.ParseFile(fset, fileName, nil, parser.ParseComments)
    if err != nil {
        return nil, err
    }

  // 类型检查, 得到常量的值
    conf := types.Config{Importer: importer.Default()}
    pkg, err := conf.Check("cmd/hello", fset, []*ast.File{f}, nil)
    if err != nil {
        return nil, err
    }
    m := make(map[string]string)
    for _, v := range f.Scope.Objects {
        if v.Kind == ast.Con {
            d := v.Decl.(*ast.ValueSpec)
            m[pkg.Scope().Lookup(v.Name).(*types.Const).Val().String()] = d.Comment.Text()
        }
    }
    return m, nil
}

3 参考资料