golang的代码结构

golang的源码中含有go fmt,go build等工具,这些工具都会涉及到对golang的源码的文件进行相关分析,因此,可以从这些工具的源代码入手,看看golang的代码是如何解析的,并将代码中的相关信息进行提取。

分析go fmt工具,入口: src/cmd/gofmt. 从main函数入口,通过查看源代码发现,可以通过go/parser的parse函数对文档进行解析,解析后返回的是一个ast.File的实例

type File struct {
    Doc        *CommentGroup   // 文档注释
    Package    token.Pos       // package位置
    Name       *Ident          // package name
    Decls      []Decl          // top-level declarations; or nil
    Scope      *Scope          // package scope (this file only)
    Imports    []*ImportSpec   // imports in this file
    Unresolved []*Ident        // unresolved identifiers in this file
    Comments   []*CommentGroup // list of all comments in the source file
}

其中,关键点在Decls,里面包含有const、var定义,结构体、函数等信息。

golang的parser函数从上到下进行解析token包中可以查看到golang的关键字、运算符等相关信息。
decl中包括const、var;type(struct,interface);func

下面是一个从代码中获取相关信息的例子(获取struct和field的注释信息)

func docStruct(fp string) {
    fs, _ := parser.ParseFile(token.NewFileSet(), fp, nil, parser.ParseComments)
    if fs.Name != nil {
        if fs.Name.Obj != nil {
        }
    }

    for _, item := range fs.Decls {
        switch item.(type) {
        case *ast.BadDecl:
        case *ast.GenDecl:
            decl := item.(*ast.GenDecl)
            for _, subitem := range decl.Specs {

                switch decl.Tok {
                case token.IMPORT:
                case token.CONST:
                case token.TYPE:
                    spec := subitem.(*ast.TypeSpec)
                    switch spec.Type.(type) {
                    case *ast.Ident:
                    case *ast.ArrayType:
                    case *ast.StructType:
                        st := spec.Type.(*ast.StructType)
                        sinfo := StructInfo{
                            Name:   spec.Name.Name,
                            Fields: StructFieldInfo(st),
                        }
                        dir := filepath.Dir(fp)
                        if strings.HasSuffix(dir, "inner") {
                            sinfo.Name = "inner_" + sinfo.Name
                        } else if strings.HasSuffix(dir, "models") {
                            sinfo.Name = "AE_" + sinfo.Name
                        } else {
                            continue
                        }
                        filestream.WriteString(fmt.Sprintf("UPDATE tableinfo SET pcomment='%s' WHERE pname='%s';\n", strings.TrimSpace(decl.Doc.Text()), sinfo.Name))
                    case *ast.StarExpr:
                    case *ast.ParenExpr:
                    case *ast.SelectorExpr:
                    }

                case token.VAR:
                }
            }

        case *ast.FuncDecl:
            //fmt.Println(item.(*ast.FuncDecl).Doc.Text())
        }
    }
}

type StructInfo struct {
    Name   string
    Fields []FieldInfo
}

type FieldInfo struct {
    Name    string
    Tag     string
    Comment string
}

func StructFieldInfo(sinfo *ast.StructType) []FieldInfo {
    if sinfo == nil || sinfo.Fields == nil {
        return []FieldInfo{}
    }
    result := make([]FieldInfo, 0)
    var info FieldInfo
    for _, field := range sinfo.Fields.List {
        info = FieldInfo{}
        for _, fnames := range field.Names {
            info.Name += fnames.Name
        }
        if field.Tag != nil {
            info.Tag = field.Tag.Value
        }
        if field.Comment != nil {
            info.Comment = strings.TrimSpace(field.Comment.Text())
        }
        result = append(result, info)
    }
    return result
}

//COMMENT ON COLUMN "private"."info"."Id" IS 'ceshi';

转载于:https://www.cnblogs.com/zp900704/p/11342000.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值