怎么用golang编写基于注解的静态代码增强器/生成器
发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,本篇内容主要讲解"怎么用golang编写基于注解的静态代码增强器/生成器",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么用golang编写基于注解的静态
千家信息网最后更新 2026年11月02日怎么用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安全错误
数据库的锁怎样保障安全
湖北九亚互联网络科技有限公司
互联网科技工作委员会毛军
科技赋能下的互联网金融
互联网金融与金融科技
成都互联网科技公司
睿民互联网科技
深圳天众互联网科技公司
互联网实体化科技化
成都玖崟互联网科技有限公司乐商圈怎么样
广州优美互联网科技
智腾互联网科技有限公司
厦门千工互联网科技有限公司
知域互联网科技有限公司大骗子
佛山市拉法互联网科技有限公司
怎样加入科技互联网
互联网营销推广黑科技
唐山双旺合互联网科技产业园
瑞安市蟠桃会互联网科技有限公司
高科技和互联网的现代国家
如何强化互联网金融科技
互联网科技产业
科技股互联网
重庆互联网络科技
苏州互联网科技贷款公司
广州善班互联网科技
互联网科技产品
互联网保险科技创业
企晟互联网信息科技有限公司
互联网公司高科技产品
山东蛋芒互联网科技有限公司