Go 获取结构字段的简单字符串表示形式’;s型
使用Go,我在结构的字段列表上循环,如下所示:Go 获取结构字段的简单字符串表示形式’;s型,go,abstract-syntax-tree,Go,Abstract Syntax Tree,使用Go,我在结构的字段列表上循环,如下所示: type Thing struct { Field1 string Field2 []int Field3 map[byte]float64 } // typ is a *ast.StructType representing the above for _, fld := range typ.Fields.List { // get fld.Type as string } …并希望获得源代码中显示的fl
type Thing struct {
Field1 string
Field2 []int
Field3 map[byte]float64
}
// typ is a *ast.StructType representing the above
for _, fld := range typ.Fields.List {
// get fld.Type as string
}
…并希望获得源代码中显示的fld.Type
的简单字符串表示形式,例如[]int
或映射[byte]float64
ast package Type属性是一个Expr
,因此我发现自己在使用类型开关和专门处理每种类型时陷入了困境——而我的唯一目标是将每个字段名右侧的纯字符串去掉,这似乎应该更简单
有一种简单的方法吗?这里有两种方法,一种是表达式的类型,最终将在编译期间解析,另一种是确定该类型的代码 翻阅这些文件,我认为第一个根本不可用。但是,您可以通过在上使用
End()
和Pos()
来获取更高版本
快速示例程序:
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
)
func main() {
src := `
package foo
type Thing struct {
Field1 string
Field2 []int
Field3 map[byte]float64
}`
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "", src, 0)
if err != nil {
panic(err)
}
// hard coding looking these up
typeDecl := f.Decls[0].(*ast.GenDecl)
structDecl := typeDecl.Specs[0].(*ast.TypeSpec).Type.(*ast.StructType)
fields := structDecl.Fields.List
for _, field := range fields {
typeExpr := field.Type
start := typeExpr.Pos() - 1
end := typeExpr.End() - 1
// grab it in source
typeInSource := src[start:end]
fmt.Println(typeInSource)
}
}
这张照片是:
string
[]int
map[byte]float64
如果你想搞乱它,我会在中一起讨论这个问题。我找到了一种方法,可以不使用原始源代码作为简单成员(而不是切片、数组或结构)的参考: 对于非简单成员,您只需要另一个case语句(即:
case*ast.ArrayType:
)。这正是go/printer
包中的目的。它将任何AST节点作为参数,并将其字符串表示形式写入io.Writer
您可以在示例中使用它,如下所示:
package main
import (
"bytes"
"fmt"
"go/ast"
"go/parser"
"go/printer"
"go/token"
"log"
)
func main() {
src := `
package foo
type Thing struct {
Field1 string
Field2 []int
Field3 map[byte]float64
}`
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "", src, 0)
if err != nil {
panic(err)
}
typeDecl := f.Decls[0].(*ast.GenDecl)
structDecl := typeDecl.Specs[0].(*ast.TypeSpec).Type.(*ast.StructType)
for i, fld := range structDecl.Fields.List {
// get fld.Type as string
var typeNameBuf bytes.Buffer
err := printer.Fprint(&typeNameBuf, fset, fld.Type)
if err != nil {
log.Fatalf("failed printing %s", err)
}
fmt.Printf("field %d has type %q\n", i, typeNameBuf.String())
}
}
输出:
field 0 has type "string"
field 1 has type "[]int"
field 2 has type "map[byte]float64"
在操场上试试:你可以使用
go/types
ExprString
这适用于复杂类型,如[]string
,[]map[string]string
等
import (
...
"go/types"
...
)
...
// typ is a *ast.StructType representing the above
for _, fld := range typ.Fields.List {
...
typeExpr := fld.Type
typeString := types.ExprString(typeExpr)
...
}
您是否尝试过文件字符串[fld.Type.Pos():fld.Type.End()]?既有帮助,也有不幸。:)文件业务在我的项目中处于上游,必须进行重组。
import (
...
"go/types"
...
)
...
// typ is a *ast.StructType representing the above
for _, fld := range typ.Fields.List {
...
typeExpr := fld.Type
typeString := types.ExprString(typeExpr)
...
}