Go AST解析场景下如何将类型转换为编译器识别的底层原始类型
解决方法
你只靠AST的语法结构无法直接拿到真实语义类型,必须搭配go/packages提供的类型检查能力一起使用,具体操作步骤如下:
步骤1:加载包时开启类型信息加载
初始化包加载配置时,除了默认的语法解析模式,额外添加类型信息相关的加载标识:
cfg := &packages.Config{ // 按需添加其他模式,必须包含下面三个 Mode: packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo, } pkgs, err := packages.Load(cfg, "./目标包路径") // 处理加载错误逻辑
步骤2:从类型信息中获取字段的真实类型
遍历AST拿到*ast.Field节点后,从加载得到的包对象的TypesInfo中取出对应的语义类型对象:
// pkg 是 packages.Load 返回的单包对象,field 是当前遍历到的参数节点 fieldSemType := pkg.TypesInfo.Types[field.Type].Type
步骤3:判断底层类型是否为int
用types.Unalias(Go 1.22+提供,用于处理类型别名)和types.Underlying递归解析到底层基础类型再做判断,types.Underlying会自动递归展开所有自定义类型定义,哪怕是多层嵌套的自定义类型(比如type MyInt int、type MyInt2 MyInt)都能最终拿到最底层的基础类型:
// 先解类型别名 rawType := types.Unalias(fieldSemType) // 取底层真实类型 underlyingType := rawType.Underlying() // 判断是否为int基础类型 if basicType, ok := underlyingType.(*types.Basic); ok && basicType.Kind() == types.Int { // 符合要求,生成你的特殊逻辑代码 }
低版本兼容说明
如果你使用的Go版本低于1.22没有types.Unalias方法,可以手动判断类型是否为*types.Alias后递归取出实际类型即可。
内容的提问来源于stack exchange,提问作者Oleg
相关产品推荐
相关产品推荐

