首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >2022-11-13:以下go语言代码中,如何获取结构体列表以及结构体内的指针方法列表?以下代码应该返回{"S1":["M1",

2022-11-13:以下go语言代码中,如何获取结构体列表以及结构体内的指针方法列表?以下代码应该返回{"S1":["M1",

作者头像
福大大架构师每日一题
发布2023-02-01 11:17:05
发布2023-02-01 11:17:05
1.5K00
代码可运行
举报
运行总次数:0
代码可运行

2022-11-13:以下go语言代码中,如何获取结构体列表以及结构体内的指针方法列表?以下代码应该返回{"S1":["M1","M2"],"S2":[],"S3":["M1","M3"]},顺序不限。S1的M3方法不是指针方法,S3的M2方法也不是指针方法,所以不能输出。

代码语言:javascript
代码运行次数:0
运行
复制
package main
type S1 struct{}
func (this *S1) M1() {}
func (this *S1) M2() {}
func (this S1) M3() {}
type S2 struct{}
type S3 struct{}
func (this *S3) M1() {}
func (this S3) M2() {}
func (this *S3) M3() {}

答案2022-11-14:

这道题有人说用反射,实际上反射是无法解决这个问题的,原因是无法直接使用结构体。

要解析rust的代码,go/ast、go/parser、go/token,要用到这三个包。

使用场景是写框架。

代码用go语言编写。代码如下:

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

import (
  "encoding/json"
  "fmt"
  "go/ast"
  "go/parser"
  "go/token"
)

const content = `package main
type S1 struct{}
func (this *S1) M1() {}
func (this *S1) M2() {}
func (this S1) M3() {}
type S2 struct{}
type S3 struct{}
func (this *S3) M1() {}
func (this S3) M2() {}
func (this *S3) M3() {}`

func main() {
  fset := token.NewFileSet()
  f, err := parser.ParseFile(fset, "", content, parser.ParseComments)
  if err != nil {
    fmt.Println(err)
    return
  }

  structInfoList := make([]*StructInfo, 0)
  structInfoMap := make(map[string]*StructInfo)

  // 找结构体
  for i := 0; i < len(f.Decls); i++ {
    decl, ok := f.Decls[i].(*ast.GenDecl)
    if !ok {
      continue
    }
    if decl.Tok != token.TYPE {
      continue
    }
    if len(decl.Specs) != 1 {
      continue
    }
    spec, ok2 := decl.Specs[0].(*ast.TypeSpec)
    if !ok2 {
      continue
    }
    structType, ok3 := spec.Type.(*ast.StructType)
    if !ok3 {
      fmt.Println("失败", structType)
      continue
    }
    structInfo := NewStructInfo(spec.Name.Name)
    structInfoList = append(structInfoList, structInfo)
    structInfoMap[spec.Name.Name] = structInfo
  }

  // 找方法
  for i := 0; i < len(f.Decls); i++ {
    decl, ok := f.Decls[i].(*ast.FuncDecl)
    if !ok {
      continue
    }
    if decl.Recv == nil || len(decl.Recv.List) != 1 {
      continue
    }
    structName := ""
    switch decl.Recv.List[0].Type.(type) {
    case *ast.StarExpr: //指针方法
      structName = decl.Recv.List[0].Type.(*ast.StarExpr).X.(*ast.Ident).Name
    case *ast.Ident: //普通方法
      //structName = decl.Recv.List[0].Type.(*ast.Ident).Name
    }
    if structInfo, ok := structInfoMap[structName]; ok {
      structInfo.MethodNameList = append(structInfo.MethodNameList, decl.Name.Name)
    }
  }

  // 输出
  data, _ := json.MarshalIndent(structInfoList, "", "  ")
  fmt.Println(string(data))
}

type StructInfo struct {
  StructName     string   `json:"structName,omitempty"`
  MethodNameList []string `json:"methodNameList,omitempty"`
}

func NewStructInfo(structName string) *StructInfo {
  return &StructInfo{StructName: structName, MethodNameList: make([]string, 0)}
}

执行结果如下:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 福大大架构师每日一题 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档