func lookupType(ty reflect.Type, path ...string) (reflect.Type, bool) { if len(path) == 0 { return ty, true } switch ty.Kind() { case reflect.Slice, reflect.Array, reflect.Map: if hasIndex(path[0]) { return lookupType(ty.Elem(), path[1:]...) } // Aggregate. return lookupType(ty.Elem(), path...) case reflect.Ptr: return lookupType(ty.Elem(), path...) case reflect.Interface: // We can't know from here without a value. Let's just return this type. return ty, true case reflect.Struct: f, ok := ty.FieldByName(path[0]) if ok { return lookupType(f.Type, path[1:]...) } } return nil, false }
func compileField(typ reflect.Type, name string, args []parse.Node, final reflect.Type) (fn lookupFn, elem reflect.Type) { if isNilType(typ) { fn = compileFieldDynamic(name, args) return } if m, exist := typ.MethodByName(name); exist { fn = compileMethodCall(typ, m.Func, args, final) elem = m.Type.Out(0) return } switch typ.Kind() { case reflect.Struct: structField, found := typ.FieldByName(name) if !found { panic(fmt.Errorf("%s has no field %s", typ, name)) } fn = func(s state, v reflect.Value, final interface{}) reflect.Value { return v.FieldByIndex(structField.Index) } elem = structField.Type return case reflect.Map: k := reflect.ValueOf(name) fn = func(s state, v reflect.Value, final interface{}) reflect.Value { return v.MapIndex(k) } elem = typ.Key() return } panic(fmt.Errorf("struct or map expected, but got %s", typ)) }
func (gfg *gofiguration) parseGofigureField(t reflect.Type) error { gf, ok := t.FieldByName("gofigure") if ok { tags := getStructTags(string(gf.Tag)) for name, value := range tags { if name == "order" { oParts := strings.Split(value, ",") for _, p := range oParts { if _, ok := Sources[p]; !ok { return ErrInvalidOrder } } gfg.order = oParts continue } // Parse orderKey:"value" tags, e.g. // envPrefix, which gets split into // gfg.params["env"]["prefix"] = "value" // gfg.params["env"] is then passed to // source registered with that key match := argRe.FindStringSubmatch(name) if len(match) > 1 { if _, ok := gfg.params[match[1]]; !ok { gfg.params[match[1]] = make(map[string]string) } gfg.params[match[1]][strings.ToLower(match[2])] = value } } } return nil }
// StructPtr generates pointers to a given struct type. // rt has to be the reflect type of the struct, gens contains a map of field generators. // Note that the result types of the generators in gen have to match the type of the correspoinding // field in the struct. Also note that only public fields of a struct can be generated func StructPtr(rt reflect.Type, gens map[string]gopter.Gen) gopter.Gen { if rt.Kind() == reflect.Ptr { rt = rt.Elem() } if rt.Kind() != reflect.Struct { return Fail(rt) } return func(genParams *gopter.GenParameters) *gopter.GenResult { result := reflect.New(rt) for name, gen := range gens { field, ok := rt.FieldByName(name) if !ok { continue } value, ok := gen(genParams).Retrieve() if !ok { return gopter.NewEmptyResult(rt) } result.Elem().FieldByIndex(field.Index).Set(reflect.ValueOf(value)) } return gopter.NewGenResult(result.Interface(), gopter.NoShrinker) } }
func typeToParamsSpecFromPath(t reflect.Type, path string) ( map[string]*ApiRequestParamSpec, error) { if t.Kind() != reflect.Struct { return nil, fmt.Errorf( "typeToParamsSpec: Only structs are supported, got: %v", t) } params := make(map[string]*ApiRequestParamSpec) pathKeys, err := parsePath(path) if err != nil { return nil, err } for _, k := range pathKeys { k = strings.Title(k) field, found := t.FieldByName(k) if !found { return nil, fmt.Errorf( "typeToParamsSpec: Can't find field %q in %v (from path %q)", k, t, path) } param, err := fieldToParamSpec(&field) if err != nil { return nil, err } param.Required = true params[field.Name] = param } return params, nil }
func isList(t reflect.Type) bool { if t.Kind() != reflect.Struct { return false } _, hasListMeta := t.FieldByName("ListMeta") return hasListMeta }
func CheckField(t *testing.T, typ reflect.Type, name string, typName string, typVal interface{}) { field, found := typ.FieldByName(name) if !found { t.Fatalf("Pas de champ '%s'", name) } if field.Type != reflect.TypeOf(typVal) { t.Fatalf("Le champ '%s' n'est pas de type %s", name, typName) } }
func getExportedField(t reflect.Type, field string) reflect.StructField { f, ok := t.FieldByName(field) if !ok { panic("field " + field + " is not found") } if len(f.PkgPath) != 0 { panic("field " + field + " is unexported") } return f }
// resolveKeyForField either returns lowercase version of the name if the field // was found or the key found in a bson struct tag or "" if the field wasn't found func resolveKeyForField(Struct reflect.Type, name string) string { if f, ok := Struct.FieldByName(name); ok { tag := f.Tag.Get("bson") parts := strings.Split(tag, ",") if len(parts) > 0 && parts[0] != "" && parts[0] != "-" { return parts[0] } else { return strings.ToLower(f.Name) } } return "" }
func columnToFieldIndex(m *DbMap, t reflect.Type, cols []string) ([][]int, error) { colToFieldIndex := make([][]int, len(cols)) // check if type t is a mapped table - if so we'll // check the table for column aliasing below tableMapped := false table := tableOrNil(m, t) if table != nil { tableMapped = true } // Loop over column names and find field in i to bind to // based on column name. all returned columns must match // a field in the i struct missingColNames := []string{} for x := range cols { colName := strings.ToLower(cols[x]) field, found := t.FieldByNameFunc(func(fieldName string) bool { field, _ := t.FieldByName(fieldName) cArguments := strings.Split(field.Tag.Get("db"), ",") fieldName = cArguments[0] if fieldName == "-" { return false } else if fieldName == "" { fieldName = field.Name } if tableMapped { colMap := colMapOrNil(table, fieldName) if colMap != nil { fieldName = colMap.ColumnName } } return colName == strings.ToLower(fieldName) }) if found { colToFieldIndex[x] = field.Index } if colToFieldIndex[x] == nil { missingColNames = append(missingColNames, colName) } } if len(missingColNames) > 0 { return colToFieldIndex, &NoFieldInTypeError{ TypeName: t.Name(), MissingColNames: missingColNames, } } return colToFieldIndex, nil }
func writeAccessorMethods(rt reflect.Type) (accSrc string) { var ( nameCases []string sf reflect.StructField sfType reflect.Type isSid bool sfName string numCase, pos int ) if _, hasSid := rt.FieldByName("HasSid"); !spref(rt.Name(), "ParamOrSid") { accSrc += sfmt("func (me *%s) AccessField(fn string) interface{} {\n\tswitch fn {\n", rt.Name()) for i := 0; i < rt.NumField(); i++ { if sf = rt.Field(i); (len(sf.Name) > 0) && (sf.Name != "Def") && (sf.Name != "Kind") && !sf.Anonymous { if isSid, sfName, sfType = spref(sf.Type.Name(), "Sid"), sf.Name, sf.Type; isSid || (hasSid && (!anyOf(sfType, reflect.Invalid, reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Struct, reflect.UnsafePointer)) && ((sfType.Kind() != reflect.Ptr) || elemType(sfType).Kind() != reflect.Struct)) { if numCase++; isSid { switch sfType.Name() { case "SidBool": sfName += ".B" case "SidString": sfName += ".S" case "SidVec3": sfName += ".Vec3" default: sfName += ".F" } } nameCases = append(nameCases, sf.Name) accSrc += sfmt("\tcase %#v:\n\t\treturn %sme.%s\n", sf.Name, ustr.Ifs(sfType.Kind() == reflect.Ptr, "", "&"), sfName) } else if pos = strings.Index(sfType.String(), "ParamOr"); pos > 0 { // numCase++ switch sfType.String()[pos+len("ParamOr"):] { case "Bool": case "RefSid": case "Float": case "SidFloat": case "Float2": case "Int": } // println(rt.Name() + "." + sf.Name + " => " + sfType.String()) } } } if accSrc += "\t}\n\treturn nil\n}\n\n"; numCase == 0 { accSrc = "" } else { accSrc = sfmt("//\tRefSidFielder implementation.\n//\tSupported field names: \"%v\".\n", strings.Join(nameCases, "\", \"")) + accSrc } } return }
func (g *conversionGenerator) generateConversionsForStruct(inType, outType reflect.Type) error { for i := 0; i < inType.NumField(); i++ { inField := inType.Field(i) outField, found := outType.FieldByName(inField.Name) if !found { return fmt.Errorf("couldn't find a corresponding field %v in %v", inField.Name, outType) } if isComplexType(inField.Type) { if err := g.generateConversionsBetween(inField.Type, outField.Type); err != nil { return err } } } return nil }
func findField(value reflect.Value, typ reflect.Type, k string, v string) (reflect.Value, reflect.StructField) { field := value.FieldByName(v) if field.IsValid() { tfield, _ := typ.FieldByName(v) return field, tfield } for ix := 0; ix < value.NumField(); ix++ { field := value.Field(ix) tfield := typ.Field(ix) if tfield.Tag.Get("AMI") == k && field.String() == v { return field, tfield } } return field, reflect.StructField{} }
func checkForInputError(fieldType reflect.Type, value interface{}) error { // We always want to check the pointer to the value (and never the // pointer to the pointer to the value) for interface matching. var emptyValue reflect.Value if fieldType.Kind() == reflect.Ptr { emptyValue = reflect.New(fieldType.Elem()) } else { emptyValue = reflect.New(fieldType) } // A type switch would look cleaner here, but we want a very // specific order of preference for these interfaces. A type // switch does not guarantee any preferred order, just that // one valid case will be executed. emptyInter := emptyValue.Interface() if validator, ok := emptyInter.(InputValidator); ok { return validator.ValidateInput(value) } if receiver, ok := emptyInter.(web_request_readers.RequestValueReceiver); ok { return receiver.Receive(value) } fieldTypeName := fieldType.Name() if fieldType.Kind() == reflect.Struct && strings.HasPrefix(fieldTypeName, SqlNullablePrefix) { // database/sql defines many Null* types, // where the fields are Valid (a bool) and the // name of the type (everything after Null). // We're trying to support them (somewhat) // here. typeName := fieldTypeName[len(SqlNullablePrefix):] nullField, ok := fieldType.FieldByName(typeName) if ok { // This is almost definitely an sql.Null* type. if value == nil { return nil } fieldType = nullField.Type } } if !reflect.TypeOf(value).ConvertibleTo(fieldType) { return errors.New("Input is of the wrong type and cannot be converted") } return nil }
func columnToFieldIndex(m *DbMap, t reflect.Type, cols []string) ([][]int, error) { colToFieldIndex := make([][]int, len(cols)) // check if type t is a mapped table - if so we'll // check the table for column aliasing below tableMapped := false table := tableOrNil(m, t) if table != nil { tableMapped = true } // Loop over column names and find field in i to bind to // based on column name. all returned columns must match // a field in the i struct for x := range cols { colName := strings.ToLower(cols[x]) field, found := t.FieldByNameFunc(func(fieldName string) bool { field, _ := t.FieldByName(fieldName) fieldName = field.Tag.Get("db") if fieldName == "-" { return false } else if fieldName == "" { fieldName = field.Name } if tableMapped { colMap := colMapOrNil(table, fieldName) if colMap != nil { fieldName = colMap.ColumnName } } return colName == strings.ToLower(fieldName) }) if found { colToFieldIndex[x] = field.Index } if colToFieldIndex[x] == nil { return nil, fmt.Errorf("gorp: No field %s in type %s", colName, t.Name()) } } return colToFieldIndex, nil }
func getStructFieldInfos(rt reflect.Type) (sis *structFieldInfos) { sis, ok := cachedStructFieldInfos[rt] if ok { return } cachedStructFieldInfosMutex.Lock() defer cachedStructFieldInfosMutex.Unlock() sis = new(structFieldInfos) var siInfo *structFieldInfo if f, ok := rt.FieldByName(structInfoFieldName); ok { siInfo = parseStructFieldInfo(structInfoFieldName, f.Tag.Get("msgpack")) } rgetStructFieldInfos(rt, nil, sis, siInfo) cachedStructFieldInfos[rt] = sis return }
func getFieldByNameInner(t reflect.Type, name string) (reflect.StructField, bool) { nameArray := Explode(name, ".") if len(nameArray) == 0 { return reflect.StructField{}, false } var isExist bool var resultStruct reflect.StructField resultIndex := []int{} for _, singleName := range nameArray { resultStruct, isExist = t.FieldByName(singleName) if !isExist { return reflect.StructField{}, false } resultIndex = append(resultIndex, resultStruct.Index...) t = resultStruct.Type } resultStruct.Index = resultIndex return resultStruct, true }
func (this *dbMap) columnsToFieldIndexList(meta reflect.Type, cols []string) ([][]int, error) { fieldIndexList := make([][]int, len(cols)) table, ok := this.getTableByMeta(meta) if !ok { table = this.getOrAddPseudoTable(meta) } for i, colName := range cols { if col, ok := table.colDict[colName]; ok { if f, ok := meta.FieldByName(col.fieldName); ok { fieldIndexList[i] = f.Index } } if fieldIndexList[i] == nil { return nil, errfTableMetaNoField(colName, table.tableName) } } return fieldIndexList, nil }
func (g *generator) generateConversionsForStruct(inType, outType reflect.Type) error { for i := 0; i < inType.NumField(); i++ { inField := inType.Field(i) outField, found := outType.FieldByName(inField.Name) if !found { return fmt.Errorf("couldn't find a corresponding field %v in %v", inField.Name, outType) } if inField.Type.Kind() != outField.Type.Kind() { return fmt.Errorf("cannot convert types of different kinds: %v %v", inField, outField) } if isComplexType(inField.Type) { if err := g.generateConversionsBetween(inField.Type, outField.Type); err != nil { return err } } } g.convertibles[inType] = outType return nil }
func nameToFieldName(t reflect.Type, name string) string { if t.Kind() == reflect.Ptr { t = t.Elem() } else if t.Kind() != reflect.Struct { return "" } // find a field matching "json" field tag if hasJsonTags(t) { return nameToFieldNameByJsonTag(t, name) } // do a fuzzy search using "tcpPort" => ["TcpPort", "TCPPort"] for _, goName := range nameToGo(name) { if f, ok := t.FieldByName(goName); ok { return f.Name } } return "" }
func instantiateAndInjectController(context gon.WebContext, controllerType reflect.Type) reflect.Value { // Instantiate a controller conValue := reflect.New(controllerType) conIndirect := reflect.Indirect(conValue) // Inject Params conIndirect.FieldByName("Params").Set(reflect.ValueOf(context.GetParams())) // // Inject beans // This loop tends to be slow. We should loop over field names and look-up a bean. // for beanName, setterFunc := range bean.Registry() { if _, ok := controllerType.FieldByName(beanName); ok { if field := conIndirect.FieldByName(beanName); field.IsValid() { field.Set(reflect.ValueOf(setterFunc())) } } } return conValue }
func makeColToFieldIndex(t reflect.Type, cols []string) [][]int { var colToFieldIndex = make([][]int, len(cols)) for x := range cols { colName := strings.ToLower(cols[x]) field, found := t.FieldByNameFunc(func(fieldName string) bool { field, _ := t.FieldByName(fieldName) tags := strings.Split(field.Tag.Get("db"), ", ") dbNameFromTag := tags[0] if dbNameFromTag == "" { return strings.ToLower(field.Name) == colName } return colName == dbNameFromTag }) if found { colToFieldIndex[x] = field.Index } } return colToFieldIndex }
func fieldValue(key string, typ reflect.Type) (mapFunc, reflect.Type) { depth := 0 for typ.Kind() == reflect.Ptr { typ = typ.Elem() depth++ } if typ.Kind() == reflect.Struct { if field, ok := typ.FieldByName(key); ok { fn := fieldValueFunc(field, depth) if fn != nil { fdepth := 0 ft := field.Type for ft.Kind() == reflect.Ptr { ft = ft.Elem() fdepth++ } switch fdepth { case 0: case 1: f := fn fn = func(h handle) handle { return getElem(f(h)) } default: f := fn fn = func(h handle) handle { v := f(h) for ii := 0; ii < fdepth; ii++ { v = getElem(v) } return h } fn = f } return fn, ft } } } return nil, nil }
func (g *conversionGenerator) generateConversionsForStruct(inType, outType reflect.Type) error { errs := []string{} for i := 0; i < inType.NumField(); i++ { inField := inType.Field(i) outField, found := outType.FieldByName(inField.Name) if !found { // aggregate the errors so we can return them at the end but still provide // best effort for generation for other fields in this type errs = append(errs, fmt.Sprintf("couldn't find a corresponding field %v in %v", inField.Name, outType)) continue } if isComplexType(inField.Type) { if err := g.generateConversionsBetween(inField.Type, outField.Type); err != nil { return err } } } if len(errs) == 0 { return nil } return fmt.Errorf(strings.Join(errs, ",")) }
func (g *schemaGenerator) javaInterfaces(t reflect.Type) []string { if _, ok := t.FieldByName("ObjectMeta"); t.Name() != "PodTemplateSpec" && ok { return []string{"io.fabric8.kubernetes.api.model.HasMetadata"} } _, hasItems := t.FieldByName("Items") _, hasListMeta := t.FieldByName("ListMeta") if hasItems && hasListMeta { return []string{"io.fabric8.kubernetes.api.model.KubernetesResource", "io.fabric8.kubernetes.api.model.KubernetesResourceList"} } return nil }
func checkCompositeLitStruct(lit *CompositeLit, t reflect.Type, env Env) (*CompositeLit, []error) { var errs, moreErrs []error // X{} is treated as if it has zero KeyValue'd elements, i.e. unspecified // elements are set to zero. This is always valid if len(lit.Elts) == 0 { return lit, nil } // gc first checks if there are ANY keys present, and then decides how // to process the initialisers. keysPresent := false for _, elt := range lit.CompositeLit.Elts { _, ok := elt.(*ast.KeyValueExpr) keysPresent = keysPresent || ok } if keysPresent { seen := make(map[string]bool, len(lit.Elts)) mixed := false for i := 0; i < len(lit.Elts); i += 1 { kv, ok := lit.CompositeLit.Elts[i].(*ast.KeyValueExpr) if !ok { elt := fakeCheckExpr(lit.CompositeLit.Elts[i], env) lit.Elts[i] = elt if !mixed { // This error only gets reported once mixed = true errs = append(errs, ErrMixedStructValues{elt}) } continue } key := fakeCheckExpr(kv.Key, env) var value Expr // Check the key is a struct member if ident, ok := key.(*Ident); !ok { value = fakeCheckExpr(kv.Value, env) errs = append(errs, ErrInvalidStructField{key}) } else { name := ident.Name if field, ok := t.FieldByName(name); !ok { value = fakeCheckExpr(kv.Value, env) errs = append(errs, ErrUnknownStructField{key, t, name}) } else { if seen[name] { errs = append(errs, ErrDuplicateStructField{ident, name}) } seen[name] = true lit.fields = append(lit.fields, field.Index[0]) value, moreErrs = checkStructField(kv.Value, field, env) if moreErrs != nil { errs = append(errs, moreErrs...) } } } lit.Elts[i] = &KeyValueExpr{KeyValueExpr: kv, Key: key, Value: value} } } else { numFields := t.NumField() var i int for i = 0; i < numFields && i < len(lit.Elts); i += 1 { field := t.Field(i) lit.Elts[i], moreErrs = checkStructField(lit.CompositeLit.Elts[i], field, env) if moreErrs != nil { errs = append(errs, moreErrs...) } lit.fields = append(lit.fields, i) } if numFields != len(lit.Elts) { errs = append(errs, ErrWrongNumberOfStructValues{lit}) } // Remaining fields are type checked reguardless of use for ; i < len(lit.Elts); i += 1 { lit.Elts[i], moreErrs = CheckExpr(lit.CompositeLit.Elts[i], env) if moreErrs != nil { errs = append(errs, moreErrs...) } } } return lit, errs }
func (x *TypeInfos) get(rtid uintptr, rt reflect.Type) (pti *typeInfo) { var ok bool x.mu.RLock() pti, ok = x.infos[rtid] x.mu.RUnlock() if ok { return } // do not hold lock while computing this. // it may lead to duplication, but that's ok. ti := typeInfo{rt: rt, rtid: rtid} ti.numMeth = uint16(rt.NumMethod()) var indir int8 if ok, indir = implementsIntf(rt, binaryMarshalerTyp); ok { ti.bm, ti.bmIndir = true, indir } if ok, indir = implementsIntf(rt, binaryUnmarshalerTyp); ok { ti.bunm, ti.bunmIndir = true, indir } if ok, indir = implementsIntf(rt, textMarshalerTyp); ok { ti.tm, ti.tmIndir = true, indir } if ok, indir = implementsIntf(rt, textUnmarshalerTyp); ok { ti.tunm, ti.tunmIndir = true, indir } if ok, indir = implementsIntf(rt, jsonMarshalerTyp); ok { ti.jm, ti.jmIndir = true, indir } if ok, indir = implementsIntf(rt, jsonUnmarshalerTyp); ok { ti.junm, ti.junmIndir = true, indir } if ok, indir = implementsIntf(rt, selferTyp); ok { ti.cs, ti.csIndir = true, indir } if ok, _ = implementsIntf(rt, mapBySliceTyp); ok { ti.mbs = true } pt := rt var ptIndir int8 // for ; pt.Kind() == reflect.Ptr; pt, ptIndir = pt.Elem(), ptIndir+1 { } for pt.Kind() == reflect.Ptr { pt = pt.Elem() ptIndir++ } if ptIndir == 0 { ti.base = rt ti.baseId = rtid } else { ti.base = pt ti.baseId = reflect.ValueOf(pt).Pointer() ti.baseIndir = ptIndir } if rt.Kind() == reflect.Struct { var omitEmpty bool if f, ok := rt.FieldByName(structInfoFieldName); ok { siInfo := parseStructFieldInfo(structInfoFieldName, x.structTag(f.Tag)) ti.toArray = siInfo.toArray omitEmpty = siInfo.omitEmpty } pi := rgetPool.Get() pv := pi.(*rgetPoolT) pv.etypes[0] = ti.baseId vv := rgetT{pv.fNames[:0], pv.encNames[:0], pv.etypes[:1], pv.sfis[:0]} x.rget(rt, rtid, omitEmpty, nil, &vv) ti.sfip, ti.sfi = rgetResolveSFI(vv.sfis, pv.sfiidx[:0]) rgetPool.Put(pi) } // sfi = sfip x.mu.Lock() if pti, ok = x.infos[rtid]; !ok { pti = &ti x.infos[rtid] = pti } x.mu.Unlock() return }
func getTypeInfo(rtid uintptr, rt reflect.Type) (pti *typeInfo) { var ok bool cachedTypeInfoMutex.RLock() pti, ok = cachedTypeInfo[rtid] cachedTypeInfoMutex.RUnlock() if ok { return } cachedTypeInfoMutex.Lock() defer cachedTypeInfoMutex.Unlock() if pti, ok = cachedTypeInfo[rtid]; ok { return } ti := typeInfo{rt: rt, rtid: rtid} pti = &ti var indir int8 if ok, indir = implementsIntf(rt, binaryMarshalerTyp); ok { ti.m, ti.mIndir = true, indir } if ok, indir = implementsIntf(rt, binaryUnmarshalerTyp); ok { ti.unm, ti.unmIndir = true, indir } if ok, _ = implementsIntf(rt, mapBySliceTyp); ok { ti.mbs = true } pt := rt var ptIndir int8 // for ; pt.Kind() == reflect.Ptr; pt, ptIndir = pt.Elem(), ptIndir+1 { } for pt.Kind() == reflect.Ptr { pt = pt.Elem() ptIndir++ } if ptIndir == 0 { ti.base = rt ti.baseId = rtid } else { ti.base = pt ti.baseId = reflect.ValueOf(pt).Pointer() ti.baseIndir = ptIndir } if rt.Kind() == reflect.Struct { var siInfo *structFieldInfo if f, ok := rt.FieldByName(structInfoFieldName); ok { siInfo = parseStructFieldInfo(structInfoFieldName, f.Tag.Get(structTagName)) ti.toArray = siInfo.toArray } sfip := make([]*structFieldInfo, 0, rt.NumField()) rgetTypeInfo(rt, nil, make(map[string]bool), &sfip, siInfo) // // try to put all si close together // const tryToPutAllStructFieldInfoTogether = true // if tryToPutAllStructFieldInfoTogether { // sfip2 := make([]structFieldInfo, len(sfip)) // for i, si := range sfip { // sfip2[i] = *si // } // for i := range sfip { // sfip[i] = &sfip2[i] // } // } ti.sfip = make([]*structFieldInfo, len(sfip)) ti.sfi = make([]*structFieldInfo, len(sfip)) copy(ti.sfip, sfip) sort.Sort(sfiSortedByEncName(sfip)) copy(ti.sfi, sfip) } // sfi = sfip cachedTypeInfo[rtid] = pti return }
//Do a raw sql query and set the result values in dest parameter. //The dest parameter can be either a struct pointer or a pointer of struct pointer.slice //This method do not support pointer field in the struct. func (q *Qbs) QueryStruct(dest interface{}, query string, args ...interface{}) error { query = q.Dialect.substituteMarkers(query) stmt, err := q.prepare(query) if err != nil { return q.updateTxError(err) } rows, err := stmt.Query(args...) if err != nil { return q.updateTxError(err) } defer rows.Close() outPtr := reflect.ValueOf(dest) outValue := outPtr.Elem() var structType reflect.Type var single bool if outValue.Kind() == reflect.Slice { structType = outValue.Type().Elem().Elem() } else { structType = outValue.Type() single = true } columns, _ := rows.Columns() fieldNames := make([]string, len(columns)) for i, v := range columns { upper := snakeToUpperCamel(v) _, ok := structType.FieldByName(upper) if ok { fieldNames[i] = upper } else { fieldNames[i] = "-" } } for rows.Next() { var rowStructPointer reflect.Value if single { //query row rowStructPointer = outPtr } else { //query rows rowStructPointer = reflect.New(structType) } dests := make([]interface{}, len(columns)) for i := 0; i < len(dests); i++ { fieldName := fieldNames[i] if fieldName == "-" { var placeholder interface{} dests[i] = &placeholder } else { field := rowStructPointer.Elem().FieldByName(fieldName) dests[i] = field.Addr().Interface() } } err = rows.Scan(dests...) if err != nil { return err } if single { return nil } outValue.Set(reflect.Append(outValue, rowStructPointer)) } return nil }
func (g *conversionGenerator) writeConversionForStruct(b *buffer, inType, outType reflect.Type, indent int) error { for i := 0; i < inType.NumField(); i++ { inField := inType.Field(i) outField, _ := outType.FieldByName(inField.Name) existsConversion := g.scheme.Converter().HasConversionFunc(inField.Type, outField.Type) if existsConversion && !g.existsDedicatedConversionFunction(inField.Type, outField.Type) { // Use the conversion method that is already defined. assignFormat := "if err := s.Convert(&in.%s, &out.%s, 0); err != nil {\n" assignStmt := fmt.Sprintf(assignFormat, inField.Name, outField.Name) b.addLine(assignStmt, indent) b.addLine("return err\n", indent+1) b.addLine("}\n", indent) continue } switch inField.Type.Kind() { case reflect.Map: if err := g.writeConversionForMap(b, inField, outField, indent); err != nil { return err } continue case reflect.Ptr: if err := g.writeConversionForPtr(b, inField, outField, indent); err != nil { return err } continue case reflect.Slice: if err := g.writeConversionForSlice(b, inField, outField, indent); err != nil { return err } continue case reflect.Interface, reflect.Struct: // Don't copy these via assignment/conversion! default: // This should handle all simple types. if inField.Type.AssignableTo(outField.Type) { assignFormat := "out.%s = in.%s\n" assignStmt := fmt.Sprintf(assignFormat, outField.Name, inField.Name) b.addLine(assignStmt, indent) continue } if inField.Type.ConvertibleTo(outField.Type) { assignFormat := "out.%s = %s(in.%s)\n" assignStmt := fmt.Sprintf(assignFormat, outField.Name, g.typeName(outField.Type), inField.Name) b.addLine(assignStmt, indent) continue } } assignStmt := "" if g.existsDedicatedConversionFunction(inField.Type, outField.Type) { assignFormat := "if err := %s(&in.%s, &out.%s, s); err != nil {\n" funcName := g.conversionFunctionName(inField.Type, outField.Type) assignStmt = fmt.Sprintf(assignFormat, funcName, inField.Name, outField.Name) } else { assignFormat := "if err := s.Convert(&in.%s, &out.%s, 0); err != nil {\n" assignStmt = fmt.Sprintf(assignFormat, inField.Name, outField.Name) } b.addLine(assignStmt, indent) b.addLine("return err\n", indent+1) b.addLine("}\n", indent) } return nil }