Skip to content

Instantly share code, notes, and snippets.

@skyjia
Last active May 25, 2020 13:27
Show Gist options
  • Save skyjia/6d4eff42cf7b03db3e91af62b2bc9455 to your computer and use it in GitHub Desktop.
Save skyjia/6d4eff42cf7b03db3e91af62b2bc9455 to your computer and use it in GitHub Desktop.
Parse go struct
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