写点什么

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

  • 2022-11-13
    北京
  • 本文字数:1406 字

    阅读完需:约 5 分钟

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

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


package maintype 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-13:


这道题有人说用反射,实际上反射是无法解决这个问题的,原因是无法直接使用结构体。要解析 rust 的代码,go/ast、go/parser、go/token,要用到这三个包。使用场景是写框架。


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


package main
import ( "encoding/json" "fmt" "go/ast" "go/parser" "go/token")
const content = `package maintype 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)}}
复制代码


执行结果如下:



发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2021-02-15 加入

还未添加个人简介

评论

发布
暂无评论
2022-11-13:以下go语言代码中,如何获取结构体列表以及结构体内的指针方法列表?以下代码应该返回{“S1“:[“M1“,“M2“],“S2“:[],“S3“:[“M1“,“M3“]},顺序不限_golang_福大大架构师每日一题_InfoQ写作社区