type Query { dog(name: String!): Dog } type DogResolver struct { m *Dog } func (r *DogResolver) Name() string { return r.m.Name } func (r *DogResolver) Age() int32 { return int32(r.m.Age) } type Dog struct { Name string Age int } Schema Resolver Model この辺がつらい!
{ for _, typeName := range types { for _, field := range s.Types[typeName].Fields { g.generateResolverField(typeName, strings.Title(field.Name), field.Type.String()) } } src := g.format() } Schemaのtypeごとに、フィールドを取得する。
の tag も参照可能。 また、Type から新たに New して interface{} として取得することもできる。 簡略化のため今回は "github.com/mitchellh/mapstructure" も使う t := reflect.TypeOf(x) m := reflect.New(t).Interface() y := reflect.ValueOf(m).Elem().Interface()
Row の各フィールドの Type を取得する func LoadModel(m interface{}, row bigtable.Row) (interface{}, error) { tp := reflect.TypeOf(m) for i := 0; i < tp.NumField(); i++ { typ := tp.Field(i) tag := strings.ReplaceAll(string(typ.Tag), "\"", "") fieldMap[tag] = typ } ... for _, itm := range row[cf] { col := itm.Column typ, ok := fieldMap[col] ...
mapstructure で Model に入れる。 mapstructure.Decode(data, m) switch t := typ.Type.Kind(); t { case reflect.String: data[typ.Name] = string(itm.Value) case reflect.Int: data[typ.Name], _ = strconv.Atoi(string(itm.Value)) … }
から Model に読み込むロジックを共通化した。 ⇨ Goのツール・モジュールを活用することで Schema first が実現できた。 対象を絞ってアプリ固有ロジックとの住み分けを見極めることが重要。 QueryResolver go generate Bigtable reflect Resolver Model parse validate Schema tag 型の SSOT