溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何使用golang編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器

發(fā)布時(shí)間:2021-10-13 09:10:43 來源:億速云 閱讀:121 作者:iii 欄目:編程語言

本篇內(nèi)容介紹了“如何使用golang編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

Spring

Spring的主要特性:
1. 控制反轉(zhuǎn)(Inversion of Control, IoC)
2. 面向容器
3. 面向切面(AspectOriented Programming, AOP)

源碼gitee地址:
https://gitee.com/ioly/learning.gooop

原文鏈接:
https://my.oschina.net/ioly

目標(biāo)

  • 參考spring boot常用注解,使用golang編寫“基于注解的靜態(tài)代碼增強(qiáng)器/生成器”

子目標(biāo)(Day 11)

  • 編寫針對(duì)@RestController的增強(qiáng)器

    • enhancer/IEnhancer.go: 定義增強(qiáng)器接口

    • enhancer/RestControllerEnhancer.go:REST控制器的增強(qiáng)實(shí)現(xiàn)

enhancer/IEnhancer.go: 定義增強(qiáng)器接口

package enhancer

import "learning/gooop/spring/autogen/domain"

// IEnhancer clones the original file and appends enhanced code
type IEnhancer interface {
	Matches(file *domain.CodeFileInfo) bool
	Enhance(file *domain.CodeFileInfo) (error, *domain.CodeFileInfo)
}

enhancer/RestControllerEnhancer.go REST控制器的增強(qiáng)實(shí)現(xiàn)

package controller

import (
	"errors"
	"fmt"
	"learning/gooop/spring/autogen/domain"
	"path"
	"strings"
)

type RestControllerEnhancer int

type 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) <= 0 {
		return errors.New("no mapping method found")
	}
	file := s.CodeFile
	addLine := func(line string) {
		file.AdditionalLines = append(file.AdditionalLines, line)
	}
	addLine(`// RegisterRestController is auto generated to implements controller.IRestController interface`)
	addLine(fmt.Sprintf(`func (me *%s) RegisterRestController(r *gin.Engine) {`, s.Name))
	for _, it := range methods {
		addLine(fmt.Sprintf(`  r.%s("%s", me.%s)`, it.httpMethod, it.httpPath, it.method.Name))
	}
	addLine(`}`)

	return nil
}

func (me *RestControllerEnhancer) ensureImport(file *domain.CodeFileInfo, p string) {
	for _, it := range file.Imports {
		if it.Package == p {
			return
		}
	}

	// add import info
	it := new(domain.ImportInfo)
	it.CodeFile = file
	it.Package = p
	file.AdditionalImports = append(file.AdditionalImports, it)
}

func (me *RestControllerEnhancer) enhanceGetMapping(method *domain.MethodInfo, a *domain.AnnotationInfo) error {
	// todo: fixme
	panic("implements me")
}

func (me *RestControllerEnhancer) enhancePostMapping(method *domain.MethodInfo, a *domain.AnnotationInfo) error {
	// todo: fixme
	panic("implements me")
}

“如何使用golang編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI