如何在Golang中获取一个包下的所有结构体?

huangapple go评论127阅读模式
英文:

How can i get all struct under a package in Golang?

问题

可以使用反射来列出一个包中所有以结构体形式定义的类型的名称或接口。以下是一个示例代码:

package main

import (
	"fmt"
	"reflect"
)

func list(packageName string) {
	pkg, err := reflect.Import(packageName)
	if err != nil {
		fmt.Println(err)
		return
	}

	types := pkg.Types()
	for _, typeName := range types {
		typeObj, err := reflect.ResolveType(typeName)
		if err != nil {
			fmt.Println(err)
			continue
		}

		if typeObj.Kind() == reflect.Struct {
			fmt.Println(typeObj.Name())
		}
	}
}

func main() {
	list("fmt")
}

预期结果:

Formatter
GoStringer
Scanner
State
Stringer

请注意,这只是一个示例代码,实际使用时可能需要根据具体情况进行调整。

英文:

Can we list all struct in the form of name or interface, under a package?
Like:

struct := list("fmt")

expected result:

Formatter
GoStringer
Scanner
State
Stringer

答案1

得分: 3

你能做的最好的方法是解析go源码(可以使用以下命令克隆:hg clone https://code.google.com/p/go/),并且提取出ast.StructType

这就是漂亮打印机所做的事情:

<!-- language-all: go -->

func (P *Printer) Type(t *AST.Type) int {
    separator := semicolon;

    switch t.form {

    case AST.STRUCT, AST.INTERFACE:
            switch t.form {
            case AST.STRUCT: P.String(t.pos, &quot;struct&quot;);
            case AST.INTERFACE: P.String(t.pos, &quot;interface&quot;);
            }
            if t.list != nil {
                    P.separator = blank;
                    P.Fields(t.list, t.end);
            }
            separator = none;

在同样的思路下,linter go/lintlint.go中也是这样做的:

	case *ast.StructType:
		for _, f := range v.Fields.List {
			for _, id := range f.Names {
				check(id, &quot;struct field&quot;)
			}
		}
	}
英文:

The best you can do is parse the go sources (which you can clone: hg clone https://code.google.com/p/go/), and isolate the ast.StructType.

That is what a pretty printer does:

<!-- language-all: go -->

func (P *Printer) Type(t *AST.Type) int {
    separator := semicolon;

    switch t.form {

    case AST.STRUCT, AST.INTERFACE:
            switch t.form {
            case AST.STRUCT: P.String(t.pos, &quot;struct&quot;);
            case AST.INTERFACE: P.String(t.pos, &quot;interface&quot;);
            }
            if t.list != nil {
                    P.separator = blank;
                    P.Fields(t.list, t.end);
            }
            separator = none;

In the same idea, the linter go/lint does the same in lint.go:

	case *ast.StructType:
		for _, f := range v.Fields.List {
			for _, id := range f.Names {
				check(id, &quot;struct field&quot;)
			}
		}
	}

huangapple
  • 本文由 发表于 2014年6月9日 18:10:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/24118011.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定