怎么用golang编写基于注解的静态代码增强器/生成器
发表于:2025-11-13 作者:千家信息网编辑
千家信息网最后更新 2025年11月13日,本篇内容主要讲解"怎么用golang编写基于注解的静态代码增强器/生成器",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么用golang编写基于注解的静态
千家信息网最后更新 2025年11月13日怎么用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编写"基于注解的静态代码增强器/生成器"
子目标(Day 7)
今天继续the hard part:struct/field/method元素的扫描
common/Tokens.go:添加数据类型的词法解析支持
scanner/IStructScanner.go: 结构体扫描器的接口及实现
common/Tokens.go
添加数据类型的词法解析支持:
分别解析基本类型/自定义类型/指针类型/数组类型/map类型
自定义类型需要注意排除'map'关键字
指针,数组和map类型都是复合类型,需递归解析
package commonimport ( "regexp" "strings" "sync")type tTokens struct { cache map[string]*regexp.Regexp rwmutex *sync.RWMutex}var Tokens = newTokensLib()func newTokensLib() *tTokens { it := new(tTokens) it.init() return it}func (me *tTokens) init() { me.cache = make(map[string]*regexp.Regexp) me.rwmutex = new(sync.RWMutex)}func (me *tTokens) MatchString(s string, p string) bool { return strings.HasPrefix(s, p)}func (me *tTokens) MatchRegexp(s string, p string) (bool, string) { me.rwmutex.RLock() r, ok := me.cache[p] me.rwmutex.RUnlock() if !ok { me.rwmutex.Lock() if r, ok = me.cache[p]; !ok { r, _ = regexp.Compile(p) } me.rwmutex.Unlock() } if r == nil { return false, "" } if !r.MatchString(s) { return false, "" } return true, r.FindString(s)}func (me *tTokens) MatchIdentifier(s string) (bool, string) { return me.MatchRegexp(s, "^[_a-zA-Z]\\w{0,99}")}func (me *tTokens) MatchSpaces(s string) (bool, string) { return me.MatchRegexp(s, "^\\s+")}func (me *tTokens) MatchDir(s string) (bool, string) { b, s := me.MatchRegexp(s, "^([a-zA-Z]\\:)?([\\\\/][^\\s/:*?<>|\\\"\\\\]+)+[\\/]?") if b { return b, s } b, s = me.MatchRegexp(s, "^\\\"([a-zA-Z]\\:)?([\\\\/][^/:*?<>|\\\"\\\\]+)+[\\/]?\\\"") if b { return b, s } b, s = me.MatchRegexp(s, "^'([a-zA-Z]\\:)?([\\\\/][^'/:*?<>|\\\"\\\\]+)+[\\/]?'") if b { return b, s } return false, ""}func (me *tTokens) MatchDataType(s string) (bool, string) { if ok,t := me.MatchBasicType(s);ok { return true, t } if ok,t := me.MatchCustomType(s);ok { return true, t } if ok,t := me.MatchPointerType(s);ok { return true, t } if ok,t := me.MatchArrayType(s);ok { return true, t } if ok,t := me.MatchMapType(s);ok { return true, t } return false, ""}func (me *tTokens) MatchBasicType(s string) (bool, string) { list := []string { "int", "string", "bool", "byte", "int32", "int64", "uint32", "uint64", "float32", "float64", "int8", "uint8", "int16", "uint16", "time.Time", } for _,it := range list { if me.MatchString(s, it) { return true, it } } return false, ""}func (me *tTokens) MatchCustomType(s string) (bool, string) { t := s b1, s1 := me.MatchRegexp(t, `^\w+\.`) if b1 { t = t[len(s1):] } b2, s2 := me.MatchRegexp(t, `^\w+`) if !b2 { return false, "" } if s2 == "map" { // map is reserved word return false, "" } return true, s1 + s2}func (me *tTokens) MatchPointerType(s string) (bool, string) { t := s if t[0] != '*' { return false,"" } t = t[1:] b, s := me.MatchDataType(t) if !b { return false, "" } return true, "*" + s}func (me *tTokens) MatchArrayType(s string) (bool, string) { t := s b1, s1 := me.MatchRegexp(s, `^\[\s*\d*\s*\]\s*`) if !b1 { return false, "" } t = t[len(s1):] b2, s2 := me.MatchDataType(t) if !b2 { return false, "" } return true, s1 + s2}func (me *tTokens) MatchMapType(s string) (bool, string) { t := s s1 := "map" if !me.MatchString(t, s1) { return false, "" } t = t[len(s1):] b2, s2 := me.MatchRegexp(t, `^\s*\[\s*`) if !b2 { return false, "" } t = t[len(s2):] b3,s3 := me.MatchDataType(t) if !b3 { return false, "" } t = t[len(s3):] b4, s4 := me.MatchRegexp(t, `^\s*\]\s*`) if !b4 { return false, "" } t = t[len(s4):] b5, s5 := me.MatchDataType(t) if !b5 { return false, "" } return true, s1 + s2 + s3 + s4 + s5}scanner/IStructScanner.go
结构体扫描器的接口及实现
package scannerimport ( "errors" "learning/gooop/spring/autogen/common" "learning/gooop/spring/autogen/domain" "regexp" "strings")type IStructScanner interface { ScanStruct(file *domain.CodeFileInfo)}type tStructScanner intfunc (me *tStructScanner) ScanStruct(file *domain.CodeFileInfo) { bInStruct := false var stru *domain.StructInfo for lineNO,line := range file.CleanLines { if bInStruct { // end? if gStructEndRegexp.MatchString(line) { bInStruct = false me.scanMethod(stru, lineNO + 1) stru = nil continue } } // start? if gStructStartRegexp.MatchString(line) { bInStruct = true ss := gStructStartRegexp.FindAllString(line, -1) stru := domain.NewStructInfo() stru.LineNO = lineNO stru.CodeFile = file stru.Name = ss[1] continue } // in struct block ok,fname,ftype := me.scanField(line) if ok { stru.AppendField(lineNO, fname, ftype) } }}func (me *tStructScanner) scanField(line string) (ok bool, fldName string, fldType string) { if !gFieldStartRegexp.MatchString(line) { return false, "","" } fldName = strings.TrimSpace(gFieldStartRegexp.FindString(line)) fldType = strings.TrimSpace(line[len(fldName):]) return true, fldName, fldType}func (me *tStructScanner) scanMethod(stru *domain.StructInfo, fromLineNO int) { for i,max := fromLineNO, len(stru.CodeFile.CleanLines);i <= max;i++ { line := stru.CodeFile.CleanLines[i] if !gMethodStartRegex.MatchString(line) { continue } ss := gMethodStartRegex.FindAllString(line, -1) // declare declare := ss[0] offset := len(declare) // receiver receiver := ss[1] if receiver != stru.Name { continue } method := domain.NewMethodInfo() // name method.Name = ss[2] // method input args e,args := me.scanMethodArgs(method, strings.TrimSpace(line[offset:])) if e != nil { panic(e) } offset += len(args) // method return args e = me.scanReturnArgs(method, strings.TrimSpace(line[offset:])) if e != nil { panic(e) } // end scan method stru.AppendMethod(method) }}func (me *tStructScanner) scanMethodArgs(method *domain.MethodInfo, s string) (error, string) { t := s offset := 0 for { // name b1, s1 := common.Tokens.MatchRegexp(t, `\w+(\s*,\s*\w+)\s+`) if !b1 { break } argNames := s1 offset += len(s1) t = s[offset:] // data type b2, s2 := common.Tokens.MatchDataType(t) if !b2 { return gInvalidMethodArgs, "" } argDataType := s2 offset += len(s2) t = s[offset:] for _,it := range strings.Split(argNames, ",") { method.AppendArgument(it, argDataType) } // ,\s+ b3, s3 := common.Tokens.MatchRegexp(t, `\s*,\s*`) if !b3 { break } offset += len(s3) t = s[offset:] } return nil, s[0:offset]}func (me *tStructScanner) scanReturnArgs(method *domain.MethodInfo, s string) error { // todo: fixme panic("implements me")}var gStructStartRegexp = regexp.MustCompile(`^\s*type\s+(\w+)\s+struct\s+\{`)var gStructEndRegexp = regexp.MustCompile(`^\s*}`)var gFieldStartRegexp = regexp.MustCompile(`^\s*\w+\s+`)var gMethodStartRegex = regexp.MustCompile(`\s*func\s+\(\s*\w+\s+\*?(\w+)\s*\)\s+(\w+)\s*\(`)var gInvalidMethodArgs = errors.New("invalid method arguments")var DefaultStructScanner IStructScanner = new(tStructScanner)到此,相信大家对"怎么用golang编写基于注解的静态代码增强器/生成器"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
类型
注解
代码
生成器
静态
增强器
生成
内容
扫描器
指针
接口
数据
数组
目标
结构
词法
学习
支持
实用
更深
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
软件开发的人上班都很忙吗
先知网络安全
网络安全公司取名
人工智能下载软件开发
初中毕业能搞软件开发吗
广电网络安全自查报告范文
北京al系统软件开发
计算机网络技术需要的软件
算法在数据库中的应用几个表格
怎么查软件服务器地址
网络安全等级保护有几个
怎么查看数据库有多少个表语法
木服务器
古风网络安全标语
关于软件开发的网站
网络安全技术月工资多少
服务器性能监控新报价相关推荐
合肥直播平台软件开发定制
sql如何显示数据库名称
软件开发市场研究调查员
寒假网络安全直播
中国网络安全官微
青浦区品质软件开发代理品牌
同上网络安全公开课
铁西区软件开发培训
网络安全危害国家安全案例
讲网络安全的凯撒
海军基地 网络安全
景德镇软件开发公司推荐
微信支付服务器设置密码