Last active
May 25, 2020 13:27
-
-
Save skyjia/6d4eff42cf7b03db3e91af62b2bc9455 to your computer and use it in GitHub Desktop.
Parse go struct
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"go/ast" | |
"go/parser" | |
"go/token" | |
"strings" | |
) | |
const src = `package foo | |
import ( | |
"fmt" | |
"time" | |
"github.com/rs/xid" | |
) | |
// 用户档案 | |
type UserProfile struct { | |
xxx int | |
UserProfileID xid.ID | |
JmUserID string | |
NickName *string | |
NickNameInitial string | |
// 生日 | |
// 格式:yyyymmdd | |
Birthday time.Time | |
Hand int | |
Gender int | |
Height int | |
Weight int | |
IsProfileCompleted bool | |
CreatedAt time.Time // 创建时间 | |
UpdatedAt time.Time // 更新时间 | |
DeletedAt *time.Time // 删除时间 | |
} | |
` | |
func main() { | |
fset := token.NewFileSet() // positions are relative to fset | |
f, err := parser.ParseFile(fset, "", src, parser.ParseComments) | |
if err != nil { | |
fmt.Println(err) | |
return | |
} | |
for _, d := range f.Decls { | |
// is "type Xxxx struct" decleration | |
if t, ok := d.(*ast.GenDecl); ok && t.Tok == token.TYPE { | |
spec := t.Specs[0] | |
if ts, ok := spec.(*ast.TypeSpec); ok { | |
// DEBUG: print whole StructType | |
// ast.Print(fset, ts) | |
printStruct(ts) | |
} | |
} | |
} | |
} | |
func printStruct(ts *ast.TypeSpec) { | |
// is a struct | |
st, ok := ts.Type.(*ast.StructType) | |
if !ok { | |
return | |
} | |
name := ts.Name | |
if !name.IsExported() { | |
// ignore not exported struct | |
return | |
} | |
// print struct name | |
fmt.Println("Struct:", name) | |
// print fields | |
for _, field := range st.Fields.List { | |
printField(field) | |
} | |
} | |
func printField(f *ast.Field) { | |
n := f.Names[0] // name | |
typ := fieldType(f.Type) | |
var c string | |
if f.Doc != nil { // 文档注释 | |
c = f.Doc.Text() | |
} else if f.Comment != nil { // 行间注释 | |
c = f.Comment.Text() | |
} | |
c = strings.TrimSpace(c) | |
// print exported field only; otherwise print nothing | |
if n.IsExported() { | |
// 注释 | |
if c != "" { | |
fmt.Println(c) | |
} | |
// 定义 | |
fmt.Println(n.Name, typ) | |
} | |
} | |
func fieldType(n ast.Node) string { | |
typ := "" | |
switch x := n.(type) { | |
case *ast.Ident: // 标准类型 | |
typ = x.Name | |
case *ast.SelectorExpr: // 包引用类型 | |
typ = fmt.Sprintf("%s.%s", x.X, x.Sel) | |
case *ast.StarExpr: // 指针类型 | |
typ = "*" + fieldType(x.X) | |
} | |
return typ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment