前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Golang ast 的使用

Golang ast 的使用

作者头像
码缘
发布于 2022-12-14 05:53:41
发布于 2022-12-14 05:53:41
95200
代码可运行
举报
文章被收录于专栏:PHP修行之路PHP修行之路
运行总次数:0
代码可运行

从文件中获取注释信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
	"go/ast"
	"go/parser"
	"go/token"
	"log"
	"path/filepath"
)

type Visitor struct {
	fset *token.FileSet
}

func (v *Visitor) Visit(node ast.Node) ast.Visitor {
	switch node.(type) {
	//判断ast分类
	case *ast.FuncDecl:
		demo := node.(*ast.FuncDecl)

		// 打印具体的注释
		println(demo.Doc.List[0].Text)

		// 可以打印出ast结构
		ast.Print(v.fset, node)
	}

	return v
}

func main() {
	fset := token.NewFileSet()

	path, _ := filepath.Abs("./demo.go")
	f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
	if err != nil {
		log.Println(err)
		return
	}

	ast.Walk(&Visitor{
		fset: fset,
	}, f)

}

demo.go 被分析文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// file commment
package main

type Article struct{}

// @GET("/get")
func (a Article) Get() {

}

// @POST("/save")
func (a Article) Save() {

}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 输出:

// @GET("/get")
// @POST("/save")

向文件中添加变量

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/format"
	"go/parser"
	"go/token"
	"log"
	"os"
	"path/filepath"
)

type Visitor struct {
	fset *token.FileSet
}

func (v *Visitor) Visit(node ast.Node) ast.Visitor {
	switch node.(type) {
	//判断ast分类
	case *ast.FuncDecl:
		demo := node.(*ast.FuncDecl)
		if demo.Name.Name == "GetModels" {

			returnStm, ok := demo.Body.List[0].(*ast.ReturnStmt)
			if !ok {
				return v
			}

			comp, ok := returnStm.Results[0].(*ast.CompositeLit)
			if !ok {
				return v
			}

			comp.Elts = append(comp.Elts, &ast.UnaryExpr{
				Op: token.AND,
				X: &ast.CompositeLit{
					Type: &ast.Ident{
						Name: "Test",
					},
				},
			})

		}

	}

	return v
}

func main() {
	fset := token.NewFileSet()

	path, _ := filepath.Abs("./models/demo.go")
	f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
	if err != nil {
		log.Println(err)
		return
	}

	ast.Walk(&Visitor{
		fset: fset,
	}, f)

	// ast.Print(fset, f)
	var output []byte
	buffer := bytes.NewBuffer(output)
	err = format.Node(buffer, fset, f)
	if err != nil {
		log.Fatal(err)
	}
	// 输出Go代码
	file, err := os.OpenFile(path, os.O_RDWR, 0766)
	if err != nil {
		log.Fatalf("open err %s", err.Error())
	}
	n, err := file.Write(buffer.Bytes())
	if err != nil {
		log.Fatalf("write err %s", err.Error())
	}
	fmt.Println(n)
	fmt.Println(buffer.String())

}

demo.go

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*
 * @Description:
 * @Author: gphper
 * @Date: 2021-07-08 20:12:04
 */
package models

import (
	"context"

	"github.com/gphper/ginadmin/configs"
	"github.com/gphper/ginadmin/pkg/loggers"
	"gorm.io/driver/mysql"

	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
)

var mapDB map[string]*gorm.DB

type GaTabler interface {
	schema.Tabler
	FillData(*gorm.DB)
	GetConnName() string
}

type BaseModle struct {
	ConnName string `gorm:"-" json:"-"`
}

func (b *BaseModle) TableName() string {
	return ""
}

func (b *BaseModle) FillData(db *gorm.DB) {}

func (b *BaseModle) GetConnName() string {
	return b.ConnName
}

// 获取链接
func GetDB(model GaTabler) *gorm.DB {

	db, ok := mapDB[model.GetConnName()]
	if !ok {
		errMsg := fmt.Sprintf("connection name%s no exists", model.GetConnName())
		loggers.LogError(context.Background(), "get_db_error", "GetDB", map[string]string{
			"msg": errMsg,
		})
	}
	return db
}


func GetModels() []interface{} {
	return []interface{}{
		&AdminUsers{}, &Article{}, &UploadType{}, &User{}
	}
} 

最终结果向 GetModels 中添加 &Test{}

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
golang自定义linter
linter的原理是通过静态代码分析,发现其中隐藏的错误或者不符合规范的地方,然后给暴露出来,提升系统的稳定性。linter扫描的过程如下:首先进行词法分析得到一系列token,然后通过语法分析得到抽象语法树,接着通过inspector或者visitor模式提取我们感兴趣的语法单元,结合我们的规范,对比发现其中的差异,将差异暴露出来。
golangLeetcode
2023/09/06
4050
golang自定义linter
《Go小技巧&易错点100例》第三十篇
在Go语言中,切片和数组是两种不同的元素,但是切片的底层是数组,并且还有一个比较重要的机制:切片共享底层数组。
闫同学
2025/03/28
530
《Go小技巧&易错点100例》第三十篇
Go语言如何自定义linter(静态检查工具)
通常我们在业务项目中会借助使用静态代码检查工具来保证代码质量,通过静态代码检查工具我们可以提前发现一些问题,比如变量未定义、类型不匹配、变量作用域问题、数组下标越界、内存泄露等问题,工具会按照自己的规则进行问题的严重等级划分,给出不同的标识和提示,静态代码检查助我们尽早的发现问题,Go语言中常用的静态代码检查工具有golang-lint、golint,这些工具中已经制定好了一些规则,虽然已经可以满足大多数场景,但是有些时候我们会遇到针对特殊场景来做一些定制化规则的需求,所以本文我们一起来学习一下如何自定义linter需求;
Golang梦工厂
2022/07/11
1.4K0
Go语言如何自定义linter(静态检查工具)
Go每日一库之125:ast(抽象语法树)
当你对GoLang AST感兴趣时,你会参考什么?文档还是源代码? 虽然阅读文档可以帮助你抽象地理解它,但你无法看到API之间的关系等等。 如果是阅读整个源代码,你会完全看懂,但你想看完整个代码我觉得您应该会很累。 因此,本着高效学习的原则,我写了此文,希望对您能有所帮助。 让我们轻松一点,通过AST来了解我们平时写的Go代码在内部是如何表示的。 本文不深入探讨如何解析源代码,先从AST建立后的描述开始。 如果您对代码如何转换为AST很好奇,请浏览深入挖掘分析Go代码。 让我们开始吧!
luckpunk
2023/09/30
1.2K0
每个 Gopher 都需要了解的 Go AST
学过编译原理的人可能听说过编译器的前端和后端,编译器的前端一般承担着词法分析、语法分析、类型检查和中间代码生成几部分工作,而编译器后端主要负责目标代码的生成和优化,也就是将中间代码翻译成目标机器能够运行的二进制机器码。
KevinYan
2024/11/23
1890
每个 Gopher 都需要了解的 Go AST
golang源码分析:goplantuml
https://github.com/jfeliu007/goplantuml/是一款工具可以解析golang源码,生成plantuml类图,它的原理是通过源码静态分析,提取结构体,接口,方法,包等属性,然后按照uml语法生成puml文件,效果如下。
golangLeetcode
2023/09/06
5900
golang源码分析:goplantuml
Go 跟踪函数调用链,理解代码更直观
defer 是 Gopher 们都喜欢的语言机制,除了捕捉 panic、延迟释放资源外,我们日常编码中还有哪些使用 defer 的小技巧呢?
贾维斯Echo
2023/11/07
4510
Go 跟踪函数调用链,理解代码更直观
golang源码分析:抽象语法树
golang提供了非常强大的工具集合,通过这些工具我们可以非常方便地进行源码的分析加工,在代码中插入我们想要的代码,或者提取源码中我们关心的信息。如何使用呢其实非常简单:
golangLeetcode
2023/03/14
4160
golang源码分析:抽象语法树
golang源码分析:easyjson(2)
github.com/mailru/easyjson@v0.7.7/easyjson/main.go
golangLeetcode
2023/09/06
2260
golang源码分析:easyjson(2)
golang代码生成
makefile在make all之前会先generated_files去进行代码生成,所以首先要理解代码生成的原理,然后才可以很好的知道 这个过程都干啥了.
sealyun
2020/02/11
3.4K0
golang代码生成
Go能实现AOP吗?
写Java的同学来写Go就特别喜欢将两者进行对比,就经常看到技术群里讨论,比如Go能不能实现Java那样的AOP啊?Go写个事务好麻烦啊,有没有Spring那样的@Transactional注解啊?
龟仙老人
2022/04/19
3K1
2022-11-13:以下go语言代码中,如何获取结构体列表以及结构体内的指针方法列表?以下代码应该返回{“S1“:[“M1“,“M2“],“S2“:[],“S
2022-11-13:以下go语言代码中,如何获取结构体列表以及结构体内的指针方法列表?以下代码应该返回{"S1":"M1","M2","S2":[],"S3":"M1","M3"},顺序不限。S1的M3方法不是指针方法,S3的M2方法也不是指针方法,所以不能输出。
福大大架构师每日一题
2022/11/13
1.2K0
2022-11-13:以下go语言代码中,如何获取结构体列表以及结构体内的指针方法列表?以下代码应该返回{“S1“:[“M1“,“M2“],“S2“:[],“S
easyjson 源码调试学习
json解析逻辑一直很繁琐,是go项目可能遇到的性能瓶颈之一。easyjson的解决思路很直观,代码量也不大,整体思路是根据源码中的结构体生成定制化的marshal和unmarshal方法,由于是定制化的,解析的时候没有反射,性能可以做到很好,下面通过调试学习了一下定制化的marshal和unmarshal方法是如何生成的。
golangLeetcode
2022/08/02
4820
easyjson 源码调试学习
2022-11-13:以下go语言代码中,如何获取结构体列表以及结构体内的指针方法列表?以下代码应该返回{"S1":["M1",
2022-11-13:以下go语言代码中,如何获取结构体列表以及结构体内的指针方法列表?以下代码应该返回{"S1":["M1","M2"],"S2":[],"S3":["M1","M3"]},顺序不限。S1的M3方法不是指针方法,S3的M2方法也不是指针方法,所以不能输出。
福大大架构师每日一题
2023/02/01
1.2K0
golang源码分析:goc集成测试覆盖率实现原理(2)
下面我们进入源代码来分析goc的具体实现,它的入口在goc.go文件里,是用来cobra的命令解析方式。
golangLeetcode
2023/03/01
1.1K0
golang源码分析:goc集成测试覆盖率实现原理(2)
开源项目|500行代码实现表达式引擎
表达式引擎,顾名思义就是将表达式解析成可执行的代码,比如:1+2,1+2*3,(1+2)*3,"hello " + "world"等,更复杂的表达式,比如:sum(1+2)+1+1/2.0等。 在golang中为什么要表达式引擎?由于golang是静态语言,无法像其他语言一样动态执行表达式,比如:1+2,"hello " + "world"等,那么就需要将表达式解析成可执行的代码。
用户1904552
2025/02/27
750
开源项目|500行代码实现表达式引擎
劫持 Golang 编译
前段时间学习了 0x7F 师傅的「dll 劫持和应用」,其中提到通过 dll 劫持来劫持编译器实现供应链攻击,不由想到 Go 中的一些机制也可以方便地实现编译劫持,于是做了一些研究和测试。
Seebug漏洞平台
2021/11/10
1.4K0
必撸系列!Go另外几个黑魔法技巧汇总
导语 |  最近一段时间,笔者重新梳理了一下go知识点,并深入地看看了它的源码,在实践中又有了新的沉淀,于是写下这篇文章和大家分享一下。 在上一篇文章《来了!Go的2个黑魔法技巧》中,笔者分享了go中两个有意思的技巧。 而最近一段时间,笔者重新梳理了一下go知识点,并深入地看看了它的源码,在实践中又有了新的沉淀,于是写下这篇文章和大家分享一下。 一、魔法:最小化运行时(minimal runtime) 我们知道,go有一层很重的运行时(runtime),包括内存管理、goroutine 调度等重要组件;这些
腾讯云开发者
2022/05/25
6340
必撸系列!Go另外几个黑魔法技巧汇总
初探 Golang 代码混淆
近年来 Golang 热度飙升,得益于其性能优异、开发效率高、跨平台等特性,被广泛应用在开发领域。在享受 Golang 带来便利的同时,如何保护代码、提高逆向破解难度也是开发者们需要思考的问题。
Seebug漏洞平台
2021/06/17
4.5K1
Go程序生命周期
本文希望能讲清楚一个Go程序从开始写下第一行代码到程序完全退出这期间都发生了什么事情,当然每个程序的执行逻辑千差万别,但这里想讲清楚的事情是所有程序都共通的事情,所有程序都需要经历的处理逻辑。
wish42
2021/10/19
8500
相关推荐
golang自定义linter
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验