千家信息网

怎么用golang实现基于注解的静态代码增强器/生成器

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇内容主要讲解"怎么用golang实现基于注解的静态代码增强器/生成器",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么用golang实现基于注解的静态
千家信息网最后更新 2026年11月01日怎么用golang实现基于注解的静态代码增强器/生成器

本篇内容主要讲解"怎么用golang实现基于注解的静态代码增强器/生成器",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么用golang实现基于注解的静态代码增强器/生成器"吧!

Spring

Spring的主要特性:1. 控制反转(Inversion of Control, IoC)2. 面向容器3. 面向切面(AspectOriented Programming, AOP)源码gitee地址:https://gitee.com/ioly/learning.gooop原文链接:https://my.oschina.net/ioly

目标

  • 参考spring boot常用注解,使用golang编写"基于注解的静态代码增强器/生成器"

    • 配置: ComponentScan,Configuration, Bean

    • Bean声明:Component, Service, Controller

    • Bean注入:Autowried

    • AOP注解:Before, After, Around, PointCut

子目标(Day 6)

  • 昨天把思路撸清楚了,今天动手实现各种词法元素的扫描

    • project.go: 扫描整个项目的所有代码文件。module名从go.mod文件里面取

    • packages.go: 递归扫描某个代码目录

    • files.go: 扫描某个go代码文件,并解析import/struct/field/method等元素

    • imports: 扫描指定代码文件的所有import

    • domain/*.go:词法元素模型集,码略

project.go

扫描整个项目的所有代码文件。module名从go.mod文件里面取

package scannerimport (        "errors"        "io/ioutil"        "learning/gooop/spring/autogen/common"        "learning/gooop/spring/autogen/domain"        "os"        "path"        "strings")func ScanProject(name, dir string) (error, *domain.ProjectInfo) {        e, module := parseModFileAndGetModuleName(dir)        if e != nil {                return e, nil        }        files, e := ioutil.ReadDir(dir)        if e != nil {                return e, nil        }        project := domain.NewProjectInfo()        project.Name = name        project.LocalDir = dir        project.Module = module        for _, file := range files {                if !file.IsDir() {                        continue                }                e, pkg := ScanPackage(project, nil, dir+"/"+file.Name())                if e != nil {                        return e, nil                } else {                        project.AppendPackage(pkg)                }        }        return nil, project}func parseModFileAndGetModuleName(dir string) (error, string) {        modfile := path.Join(dir, gModuleFile)        _, e := os.Stat(modfile)        if e != nil {                return gErrorModuleFileNotFound, ""        }        data, e := ioutil.ReadFile(modfile)        if e != nil {                return e, ""        }        text := string(data)        for _, line := range strings.Split(text, "\n") {                line := strings.TrimSpace(line)                if !common.Tokens.MatchString(line, gModulePrefix) {                        continue                }                if ok, s := common.Tokens.MatchRegexp(line, gModulePattern); ok {                        return nil, strings.TrimSpace(s[len(gModulePrefix)+1:])                }        }        return gErrorProjectModuleNotFound, ""}var gModuleFile = "go.mod"var gModulePrefix = "module"var gModulePattern = "^module\\s+\\w+(/\\w+)*"var gErrorModuleFileNotFound = errors.New("module file not found: go.mod")var gErrorProjectModuleNotFound = errors.New("project module not found in go.mod")

packages.go

递归扫描某个代码目录

package scannerimport (        "io/ioutil"        "learning/gooop/spring/autogen/domain"        "path/filepath"        "strings")func ScanPackage(project *domain.ProjectInfo, parent *domain.PackageInfo, dir string) (error, *domain.PackageInfo) {        pkg := domain.NewPackageInfo()        pkg.Project = project        pkg.Parent = parent        pkg.LocalDir = dir        _, f := filepath.Split(dir)        pkg.Name = f        files, e := ioutil.ReadDir(dir)        if e != nil {                return e, nil        }        for _, file := range files {                if file.IsDir() {                        e, p := ScanPackage(project, pkg, dir+"/"+file.Name())                        if e != nil {                                return e, nil                        } else if p != nil {                                pkg.AppendPackage(p)                        }                } else if strings.HasSuffix(file.Name(), ".go") {                        e, f := ScanCodeFile(pkg, dir+"/"+file.Name())                        if e != nil {                                return e, nil                        } else if f != nil {                                pkg.AppendFile(f)                        }                }        }        return nil, pkg}

files.go

读入某个go代码文件,清除注释,然后解析import/struct/field/method等元素

package scannerimport (        "io/ioutil"        "learning/gooop/spring/autogen/common"        "learning/gooop/spring/autogen/domain"        "regexp"        "strings"        "unicode")func ScanCodeFile(pkg *domain.PackageInfo, file string) (error, *domain.CodeFileInfo) {        fbytes, e := ioutil.ReadFile(file)        if e != nil {                return e, nil        }        ftext := string(fbytes)        lines := strings.Split(ftext, "\n")        for i, it := range lines {                lines[i] = strings.TrimRightFunc(it, unicode.IsSpace)        }        codeFile := domain.NewCodeFileInfo()        codeFile.Package = pkg        codeFile.RawLines = lines        // clean comments        bInParaComment := false        cleanLines := make([]string, len(lines))        for i, it := range lines {                s := it                if bInParaComment {                        // para comment end?                        i := strings.Index(it, gParaCommentEnd)                        if i >= 0 {                                bInParaComment = false                                s = s[i+1:]                        } else {                                cleanLines[i] = ""                                continue                        }                }                if common.Tokens.MatchString(it, gLineCommentPrefix) {                        cleanLines[i] = ""                        continue                }                s = removeParaCommentInLine(it)                i1 := strings.Index(s, gParaCommentStart)                if i1 >= 0 {                        s = s[:i1]                        bInParaComment = true                }                cleanLines[i] = s        }        // parse imports        ScanImport(codeFile)        // todo: parse struct declares/fields/methods        return nil, nil}func removeParaCommentInLine(s string) string {        arr := gParaCommentInLine.FindAllStringIndex(s, -1)        if len(arr) > 0 {                for i := len(arr) - 1; i >= 0; i-- {                        from := arr[i][0]                        to := arr[i][1]                        s = s[:from] + s[to+1:]                }        }        return s}var gLineCommentPrefix = "^\\s*//"var gParaCommentInLine = regexp.MustCompile("/\\*.*\\*/")var gParaCommentStart = "/*"var gParaCommentEnd = "*/"

imports.go

扫描指定代码文件的所有import

package scannerimport (        "learning/gooop/spring/autogen/domain"        "regexp")func ScanImport(file *domain.CodeFileInfo) {        parseSingleImport(file)        parseMultiImports(file)}func parseSingleImport(file *domain.CodeFileInfo) {        for _, it := range file.CleanLines {                if gSingleImportRegexp.MatchString(it) {                        ss := gSingleImportRegexp.FindAllStringSubmatch(it, -1)[0]                        imp := domain.NewImportInfo()                        imp.File = file                        if len(ss) == 3 {                                imp.Alias = ""                                imp.Package = ss[1]                        } else if len(ss) == 5 {                                imp.Alias = ss[1]                                imp.Package = ss[3]                        }                        file.AppendImport(imp)                }        }}func parseMultiImports(file *domain.CodeFileInfo) {        bInBlock := false        for _, it := range file.CleanLines {                if bInBlock {                        if gMultiImportEnd.MatchString(it) {                                bInBlock = false                                continue                        }                        if gImportPackage.MatchString(it) {                                ss := gImportPackage.FindAllStringSubmatch(it, -1)[0]                                imp := domain.NewImportInfo()                                imp.File = file                                if len(ss) == 3 {                                        imp.Alias = ""                                        imp.Package = ss[1]                                } else if len(ss) == 5 {                                        imp.Alias = ss[2]                                        imp.Package = ss[3]                                }                        }                }                if gMultiImportStart.MatchString(it) {                        bInBlock = true                        continue                }        }}var gSingleImportRegexp = regexp.MustCompile(`\s*import\s+((\w+|\.)\s+)?("\w+(/\w+)*")`)var gMultiImportStart = regexp.MustCompile(`^\s*import\s+\(`)var gMultiImportEnd = regexp.MustCompile(`^\s*\)`)var gImportPackage = regexp.MustCompile(`^\s*((\w+|\.)\s+)?("\w+(/\w+)*")`)

到此,相信大家对"怎么用golang实现基于注解的静态代码增强器/生成器"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

代码 文件 注解 生成器 静态 增强器 生成 元素 内容 目录 目标 词法 项目 递归 学习 实用 更深 清楚 兴趣 切面 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 苏州找大状互联网科技有限公司 今日互联网科技 广州宏创互联网科技 互联网科技论坛 成都狮子座互联网科技 互联网科技中介 互联网科技项目计划书材料类 科技互联网大厂 呼和浩特新华互联网科技学院 开一家科技互联网公司需要多少钱 米聚互联网科技南京有限公司排面 互联网新科技动漫ppt素材 黑科技 体验场景 互联网大会 杭州披云加互联网科技有限公司 世界互联网科技成果奖 互联网科技机房 上海万顺科技互联网有限公司招聘 互联网金融运营模式中的金融科技 现代互联网科技公司 广州全民伙伴互联网科技有限公司 湖南永感互联网科技有限公司 苏州找大状互联网科技有限公司 西安互联网科技 以房互联网科技 互联网 科技服务平台 互联网科技生活的内容 互联网之后的科技是什么 福州新华互联网科技学校 知乎 华夏互联网科技业 互联网高科技绘画
0