本篇内容主要讲解“怎么用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 scanner
import (
"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 scanner
import (
"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 scanner
import (
"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 scanner
import (
"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实现基于注解的静态代码增强器/生成器”有了更深的了解,不妨来实际操作一番吧!这里是创新互联网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
分享题目:怎么用golang实现基于注解的静态代码增强器/生成器
文章位置:http://www.jxjierui.cn/article/ghohih.html


咨询
建站咨询
