あるstruct構造の中のdbというタグの内容に何が含まれているかをすべて取得したい時があったため。
たとえばこういう構造があったとして
type Timestamp struct { CreatedAt time.Time `db:"created_at"` UpdatedAt time.Time `db:"updated_at"` } type JsonField struct { Foo string `json:"foo"` Bar string `json:"bar"` } type Post struct { ID int64 `db:"id"` UserID int64 `db:"user_id"` Body string `db:"body"` PostedAt time.Time `db:"posted_at"` Deleted bool `db:"deleted"` NoName string `db:"-"` JsonBody JsonField `db:"json_body"` Timestamp }
dbタグに含まれる以下の文字列を全て取得したい。
id user_id body posted_at deleted json_body created_at updated_at
reflectで頑張る
再帰的に取ってくるのをreflectを使って自分で頑張るとこんな感じ。
func main() { p := Post{} dbTags := extractDBTags(reflect.TypeOf(p)) for _, tag := range dbTags { fmt.Println(tag) } } func extractDBTags(t reflect.Type) []string { if t.Kind() == reflect.Ptr { t = t.Elem() } dbTags := make([]string, 0) for i := 0; i < t.NumField(); i++ { f := t.Field(i) // Get the `db` tag if any dbTag, ok := f.Tag.Lookup("db") if ok && dbTag != "-" { dbTags = append(dbTags, dbTag) } // If this is an embedded struct, recurse if f.Type.Kind() == reflect.Struct { dbTags = append(dbTags, extractDBTags(f.Type)...) continue } } return dbTags }
jmoiron/sqlx/reflectx を使う
https://pkg.go.dev/github.com/jmoiron/sqlx/reflectx を使うとちょっと簡単に実装できる。
func main() { m := reflectx.NewMapper("db") fields := m.TypeMap(reflect.TypeOf(p)) for tagname, _ := range fields.Names { if !strings.Contains(tagname, ".") { fmt.Println(tagname) } } }
このやり方の場合、if !strings.Contains(tagname, ".") {
の条件がないと、json_body.Fooみたいなのも入ってきてしまうのが難しいところ。もしかしたらもっといい方法あるかも。