怎么用golang编写基于注解的静态代码增强器/生成器
发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,本篇内容主要讲解"怎么用golang编写基于注解的静态代码增强器/生成器",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么用golang编写基于注解的静态
千家信息网最后更新 2025年02月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编写"基于注解的静态代码增强器/生成器"
子目标(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安全错误
数据库的锁怎样保障安全
技术好的浪潮服务器经销联系方式
花都区软件开发就业
郑州爱普网络技术有限公司
深圳市房易网络技术
信息网络安全法的认识
萧山成典网络技术有限公司
集群和服务器
网络安全课心得60字
网络安全税务应对策略
ar博物馆导览软件开发难度
数据库原理及应用第二版高凯教材
软件开发服务费属于什么科目
服务器远程管理口授权
堡垒机与数据库审计区别
淘宝刷单软件开发公司
红帽子数据库版本怎么看
淘宝如何看物流数据库
网络安全生产教育培训会
深圳超级小网络技术有限公司
软件开发技术提取音频
安庆求职招聘软件开发定制公司
网络安全的三观三监测是什么
数据库用什么符号最好
数据库定义一个int型变量
魔兽网络安全任务怎么做
护苗网络安全课堂第三课
软件开发的维护与测试
军人网络安全宣传图片
软件开发工程属于哪类项目
甘肃微信小程序软件开发