Golang 使用 AST 获取方法和参数名以及应用举例

背景

在做一些自动生成的代码工作时,有时需要知道方法以及对应的参数名

如果仅是方法,利用反射机制就可以解决

而参数名,程序编译后,已经丢失

可以通过 AST 事先获取方法的参数名

有了方法、参数名,加上反射,那么就可以方便生成胶水代码,自动集成进 HTTP 、 gRPC 等

获取方法、参数名的例子

下面的例子,从特定包 flagInput ,特定的结构体 flagStructName ,获取该结构体所有的方法,以及对应的参数名:

	conf := &packages.Config{Mode:       packages.LoadAllSyntax,Tests:      false,}packages, err := packages.Load(conf, flagInput)if err != nil {fmt.Println("Error loading packages:", err)return}allPackages = packagesfor _, pkg := range packages {if pkg.Name != flagPackageName {continue}for _, info := range pkg.TypesInfo.Defs {if info == nil {continue}structType, ok := info.Type().(*types.Named)if !ok {continue}if structType.Obj().Name() != flagStructName {continue}for i := 0; i < structType.NumMethods(); i++ {method := structType.Method(i)methodName := method.Name()if _, ok := excludeMethods[method.Name()]; ok {continue}sig := method.Type().(*types.Signature)params := make([]string, sig.Params().Len())for i := 0; i < sig.Params().Len(); i++ {params[i] = sig.Params().At(i).Name()}allMethods[methodName] = paramssortMethods = append(sortMethods, methodName)}}}

可以把这些信息写入 map 声明,这样代码里就有类似反射参数的功能了。类似:

var methods = map[string][]string{"Method1": { "userid", "playerid", "otherparam1", "otherparam2" },"Method2": { "userid", "playerid" },
}

集成 HTTP 服务的例子

如有以下类似模板 register.tmpl:

func RegisterMethod(engine *gin.Engine) {{{ range .Methods -}}engine.Any(HttpPrefix+"{{.}}", func(context *gin.Context) { HandleGin(context, "{{.}}") }){{ end -}}
}

通过类似以下代码:

	tmpl, err := template.ParseFiles(flagTmpl)if err != nil {panic(err)}var buf bytes.Buffererr = tmpl.Execute(&buf, map[string]interface{}{"Methods": sortMethods})if err != nil {panic(err)}

就可以自动生成到 HTTP 的胶水代码:

func RegisterMethod(engine *gin.Engine) {engine.Any(HttpPrefix+"Method1", func(context *gin.Context) { HandleGin(context, "Method1") })engine.Any(HttpPrefix+"Method2", func(context *gin.Context) { HandleGin(context, "Method2") })
}

例子中的 HandleGin 函数实现,则可以:

  1. 利用方法及对应的参数信息,获取实际参数值
  2. 利用反射,实现对应结构体函数的调用

其他例子

如生成函数的接口调用说明:

模板类似:

{{ range .Methods -}}
{{.Index}}.{{.Comment}} http://api/{{.MethodName}}?{{ range $index, $param := .Params }}{{ if $index }}&{{ end }}{{ $param }}=0{{ end }}
{{ end -}}

还是基于上面的获取的方法、参数名的 map 实例信息,就可以展开了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/628087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode-83删除排序链表中的重复元素

题目链接 83. 删除排序链表中的重复元素 - 力扣&#xff08;LeetCode&#xff09; 解题代码 # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val val # self.next next class Solution:def d…

环保时代下的品牌全球化之路:绿色供应链的战略洞察

随着全球化的深入和消费者对可持续发展和环保的日益关注&#xff0c;品牌出海不仅需要考虑市场扩张和竞争力提升&#xff0c;还需要认真思考如何在全球供应链中构建绿色可持续的供应链体系。本文Nox聚星将和大家探讨品牌出海的绿色供应链建设&#xff0c;分析可持续发展和环保要…

系统学习Python——警告信息的控制模块warnings:常用函数-[warnings.formatwarning]

分类目录&#xff1a;《系统学习Python》总目录 函数 warnings.formatwarning(message, category, filename, lineno, lineNone)以标准方式格式化一条警告信息。将返回一个字符串&#xff0c;可能包含内嵌的换行符&#xff0c;并以换行符结束。如果未提供line&#xff0c;form…

机器学习扩散模型简介

一、说明 扩散模型的迅速崛起是过去几年机器学习领域最大的发展之一。在这本易于理解的指南中了解您需要了解的有关扩散模型的所有信息。 扩散模型是生成模型&#xff0c;在过去几年中越来越受欢迎&#xff0c;这是有充分理由的。仅在 2020 年代发布的几篇开创性论文就向世界…

MySQL系列之数据导入导出

前言 大数据与云计算作为当今时代&#xff0c;数据要素发展的“动力引擎”&#xff0c;已经走进了社会生活的方方方面。而背后承载的云服务或数据服务的高效运转&#xff0c;起了决定作用。 作为数据存储的重要工具&#xff0c;数据库的品类和特性也日新月异。从树型、网络型…

MySQL/Oracle 的 字符串拼接

目录 MySQL、Oracle 的 字符串拼接1、MySQL 的字符串拼接1.1 CONCAT(str1,str2,...) : 可以拼接多个字符串1.2 CONCAT_WS(separator,str1,str2,...) : 指定分隔符拼接多个字符串1.3 GROUP_CONCAT(expr) : 聚合函数&#xff0c;用于将多行的值连接成一个字符串。 2、Oracle 的字…

python调试可以看到每个变量的值吗

Python在调试窗口查看变量的值 看来想鼠标移上去就看到变量值是不可能了吧。 边修改代码边实时查看变量值&#xff0c;热更新&#xff0c;热重载咋样&#xff1f; 在开发过程中&#xff0c;调试是一项非常重要的技能。当我们编写复杂的程序时&#xff0c;很容易出现bug或逻辑…

C#灵活控制多线程的状态(开始暂停继续取消)

ManualResetEvent类 ManualResetEvent是一个同步基元&#xff0c;用于在多线程环境中协调线程的执行。它提供了两种状态&#xff1a;终止状态和非终止状态。 在终止状态下&#xff0c;ManualResetEvent允许线程继续执行。而在非终止状态下&#xff0c;ManualResetEvent会阻塞线…

Python画球面投影图

天文学研究中&#xff0c;有时候需要画的并不是传统的XYZ坐标系&#xff0c;而是需要画一个形如这样子的球面投影图&#xff1a; 下面讲一下这种图怎么画 1. 首先要安装healpy包 pip install healpy 2. 然后导入包 如果之前安装过healpy&#xff0c;有的会提示不存在healpy…

【蓝桥杯日记】第一篇——如何搭建系统环境

目录 前言 环境相关文件 学生机环境-Web应用开发环境&#xff08;第十五届大赛&#xff09; 学生机环境-Java编程环境&#xff08;第十五届大赛&#xff09; 学生机环境-C/C编程环境&#xff08;第十五届大赛&#xff09; 学生机环境-Python编程环境 &#xff08;第十五届…

20240112让移远mini-PCIE接口的4G模块EC20在Firefly的AIO-3399J开发板的Android11下跑通【DTS部分】

20240112让移远mini-PCIE接口的4G模块EC20在Firefly的AIO-3399J开发板的Android11下跑通【DTS部分】 2024/1/12 16:20 https://blog.csdn.net/u010164190/article/details/79096345 [Android6.0][RK3399] PCIe 接口 4G模块 EC20 调试记录 https://blog.csdn.net/hnjztyx/artic…

【Linux】线程池实现

&#x1f4d7;线程池实现&#xff08;单例模式&#xff09; 1️⃣线程池概念2️⃣线程池代码样例3️⃣部分问题与细节&#x1f538;类成员函数参数列表中隐含的this指针&#x1f538;单例模式&#x1f538;一个失误导致的bug 4️⃣调用线程池完成任务 1️⃣线程池概念 线程池是…

Python与CAD系列高级篇(二十四)分类提取坐标到excel

目录 0 简述1 分类提取坐标到excel2 结果展示0 简述 本篇介绍以下功能开发:1.对点、直线、多段线、圆、样条曲线分类读取坐标;2.提取坐标到excel。 1 分类提取坐标到excel 需求: ① 用户选择内容。 ② 对选定内容分类提取坐标。 ③ 提取坐标到excel。 代码实现: import m…

Unity填坑-CullingGroup的运用

Unity填坑-CullingGroup的运用 可以使用CullingGroup动态剔除一些对性能有极大影响的脚本、及渲染的进行。 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Unity填坑-CullingGroup的运用前言二、示例代码如下总结…

【Linux驱动】设备树中指定中断 | 驱动中获得中断 | 按键中断实验

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《Linux驱动》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f3c0;在设备树中指定中断&#x1f3c0;代码中获得中断&#x1f3c0;按键中断⚽驱动…

闪存剩下内容

1&#xff1a;通过Arduino IDE向闪存文件系统上传文件 1. 下载 Arduino-ESP8266闪存文件插件程序 2&#xff1a;使用闪存文件系统建立功能更加丰富的网络服务器 1&#xff1a;在网页中加载闪存文件系统中的图片、CSS和JavaScript index.html&#xff1a;ESP8266开发板建立的网…

SpringBoot+SSM项目实战 苍穹外卖(12) Apache POI

继续上一节的内容&#xff0c;本节是苍穹外卖后端开发的最后一节&#xff0c;本节学习Apache POI&#xff0c;完成工作台、数据导出功能。 目录 工作台Apache POI入门案例 导出运营数据Excel报表 工作台 工作台是系统运营的数据看板&#xff0c;并提供快捷操作入口&#xff0c…

初识OpenCV

首先你得保证你的虚拟机Ubuntu能上网 可看 http://t.csdnimg.cn/bZs6c 打开终端输入 sudo apt-get install libopencv-dev 回车 输入密码 回车 遇到Y/N 回车 OpenCV在线文档 opencv 文档链接 点zip可以下载&#xff0c;点前面的直接在线浏览&#xff0c;但是很慢 https…

c# 视频流压缩

在C#中进行视频流的压缩通常涉及到使用第三方库来处理编解码工作&#xff0c;H.264是一种广泛应用且高效的视频编码标准。以下是一个简化的例子说明如何使用SharpAvi库&#xff08;一个用于生成AVI文件并支持H.264编码的.NET库&#xff09;创建包含H.264编码视频流的AVI文件&am…

Redis的实现四:事件循环和计时器

我们的服务器缺少了一个内容&#xff1a;超时。每个网络应用程序都需要处理超时&#xff0c;因为网络的另一边可能会消失。不要只进行持续的IO操作&#xff0c;如读/写需要超时&#xff0c;但启动空闲的TCP连接也是一个好主意。要实现超时&#xff0c;必须修改事件循环&#xf…