How to write an annotation-based static code enhancer / generator using golang
This article introduces the knowledge of "how to write an annotation-based static code enhancer / generator using golang". Many people will encounter this dilemma in the operation of actual cases, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
The main features of SpringSpring: 1. Control inversion (Inversion of Control, IoC) 2. Facing Container 3. Aspect-oriented (AspectOriented Programming, AOP) source gitee address: https://gitee.com/ioly/learning.gooop original text link: https://my.oschina.net/ioly target
Refer to the common notes in spring boot and write "Annotation-based static Code Enhancer / Generator" in golang.
Subgoal (Day 11)
Write an enhancer for @ RestController
Enhancer/IEnhancer.go: define the intensifier interface
Enhanced implementation of enhancer/RestControllerEnhancer.go:REST Controller
Enhancer/IEnhancer.go: define the intensifier interface
Package enhancerimport "learning/gooop/spring/autogen/domain" / / IEnhancer clones the original file and appends enhanced codetype IEnhancer interface {Matches (file * domain.CodeFileInfo) bool Enhance (file * domain.CodeFileInfo) (error, * domain.CodeFileInfo)}
Enhanced implementation of enhancer/RestControllerEnhancer.go REST Controller
Package controllerimport ("errors"fmt"learning/gooop/spring/autogen/domain"path"strings") type RestControllerEnhancer inttype tMappingMethodInfo struct {httpMethod string httpPath string method * domain.MethodInfo} func (me * RestControllerEnhancer) Matches (file * domain.CodeFileInfo) bool {for _, it: = range file.Structs {if ok, _: = me.hasAnnotation (it.Annotations "RestController") Ok {return true}} return false} func (me * RestControllerEnhancer) Enhance (file * domain.CodeFileInfo) (error, * domain.CodeFileInfo) {/ / clone file file = file.Clone (). (* domain.CodeFileInfo) file.LocalFile = strings.Replace (file.LocalFile, ".go", "_ Enhanced.go" -1) / find structs with @ RestController changed: = false for _, it: = range file.Structs {if ok, a: = me.hasAnnotation (it.Annotations, "RestController") Ok {/ / enhance target struct e: = me.enhanceStruct (it, a) if e! = nil {return e Nil} changed = true}} if changed {return nil, file} else {return nil, nil}} func (me * RestControllerEnhancer) hasAnnotation (arr [] * domain.AnnotationInfo, name string) (bool, * domain.AnnotationInfo) {for _ It: = range arr {if it.Name = = name {return true, it}} return false, nil} func (me * RestControllerEnhancer) enhanceStruct (s * domain.StructInfo, sa * domain.AnnotationInfo) error {/ / update struct name s.Name = s.Name + "_ Enhanced" / / ensure imports me.ensureImport (s.CodeFile "github.com/gin-gonic/gin") me.ensureImport (s.CodeFile, "net/http") / / enhance GetMapping methods methods: = [] * tMappingMethodInfo {} for _, it: = range s.Methods {if ok, a: = me.hasAnnotation (it.Annotations, "GetMapping") Ok {e: = me.enhanceGetMapping (it A) if e! = nil {return e} info: = new (tMappingMethodInfo) info.httpMethod = "GET" info.httpPath = path.Join (sa.Get ("path") A.Get ("path") info.method = it methods = append (methods, info)}} / / enhance PostMapping methods for _, it: = range s.Methods {if ok, a: = me.hasAnnotation (it.Annotations, "PostMapping") Ok {e: = me.enhancePostMapping (it A) if e! = nil {return e} info: = new (tMappingMethodInfo) info.httpMethod = "POST" info.httpPath = path.Join (sa.Get ("path") A.Get ("path") info.method = it methods = append (methods, info)}} / / generate RegisterRestController () if len (methods)