package f5 import ( "database/sql" "q5" "reflect" "errors" ) type DataSet struct { columns []string rows [][]interface{} currRow []interface{} numOfReaded int64 closed bool } //已读取函数(调用Next成功的次数) func (this *DataSet) NumOfReaded() int64 { return this.numOfReaded } func (this *DataSet) close() { this.closed = true } func (this *DataSet) init(rows *sql.Rows) { if rows == nil { return } defer rows.Close() if len(this.columns) <= 0 { columns, err := rows.Columns() if err == nil { this.columns = columns } else { panic("NewDataSet Next Columns error:" + err.Error()) } } q5.NewSlice(&this.rows, 0, 100) for rows.Next() { values := []interface{}{} for i := 0; i < len(this.columns); i++ { str := sql.NullString{} values = append(values, &str) } err := rows.Scan(values...) if err != nil { panic("NewDataSet Next Scan error:" + err.Error()) } q5.AppendSlice(&this.rows, values) } } func (this *DataSet) Next() bool { /* if this.closed { panic("NewDataSet is closed") }*/ if this.numOfReaded >= int64(len(this.rows)) { return false } this.currRow = this.rows[this.numOfReaded] this.numOfReaded += 1 return true } func (this *DataSet) GetColumns() []string { return this.columns } /* 安全版:nil值视为"" */ func (this *DataSet) GetValues() *[]string { values := []string{} for _, val := range this.currRow { raw_val := val.(*sql.NullString) if raw_val.Valid { values = append(values, raw_val.String) } else { values = append(values, *q5.NewEmptyStrPtr()) } } return &values } /* 安全版:nil值视为"" */ func (this *DataSet) GetByName(name string) string { val := this.GetRawValueByName(name) if val == nil { return "" } else { return *val } } /* 安全版:nil值视为"" */ func (this *DataSet) GetByIndex(index int32) string { val := this.GetRawValueByIndex(index) if val == nil { return "" } else { return *val } } /* !!!原始版: 调用方应处理值为nil的情况 */ func (this *DataSet) GetRawValues() *[]string { values := []*string{} for _, val := range this.currRow { raw_val := val.(*sql.NullString) if raw_val.Valid { values = append(values, &raw_val.String) } else { values = append(values, nil) } } return nil } /* !!!原始版: 调用方应处理值为nil的情况 */ func (this *DataSet) GetRawValueByName(name string) *string { this.GetColumns() for i := 0; i < len(this.columns); i++ { if this.columns[i] == name { return this.GetRawValueByIndex(int32(i)) } } return nil } /* !!!原始版: 调用方应处理值为nil的情况 */ func (this *DataSet) GetRawValueByIndex(index int32) *string { this.GetColumns() sql_val := this.currRow[index].(*sql.NullString) if sql_val.Valid { return &sql_val.String } else { return nil } } func UnmarshalModelList[T any](ds *DataSet, models *[]*T) error { var resultErr error for ds.Next() { p := new(T) resultErr = UnmarshalModel(ds, p) if resultErr != nil { *models = (*models)[:0] break } q5.AppendSlice(models, p) } return resultErr } /* 只支持1级指针 */ func UnmarshalModel[T any](ds *DataSet, m *T) error { mType := reflect.TypeOf(m).Elem() mVal := reflect.ValueOf(m).Elem() for i := 0; i < mType.NumField(); i++ { field := mType.Field(i) gormTag := field.Tag.Get("gorm") if gormTag == "" { continue } gormFieldName := "" gormIsJson := false params := q5.StrSplit(gormTag, ";") for _, val := range params { tmpStrs := q5.StrSplit(val, ":") if len(tmpStrs) == 2 { if tmpStrs[0] == "column" { gormFieldName = tmpStrs[1] } if tmpStrs[0] == "serializer" { gormIsJson = true if tmpStrs[1] != "json" { return errors.New("gorm unknow serializer:" + tmpStrs[1]) } } } } if gormFieldName == "" { return errors.New("gormFieldName is empty") } fieldVal := ds.GetByName(gormFieldName) if gormIsJson { q5.DecodeJson(fieldVal, mVal.Field(i).Addr().Interface()) } else { if (q5.IsSimpleReflectKind(field.Type.Kind())) { mVal.Field(i).Set(*q5.StrToSimpleReflectValue(fieldVal, field.Type.Kind())) } else { switch field.Type.Kind() { case reflect.Ptr: { if (q5.IsSimpleReflectKind(field.Type.Elem().Kind())) { mVal.Field(i).Set(*q5.StrToSimplePtrReflectValue(fieldVal, field.Type.Elem().Kind())) } else { GetSysLog().Info("UnmarshalModel unknow fieldPtrType:%s", field.Type.Elem()); } } default: { GetSysLog().Info("UnmarshalModel unknow fieldType:%s", field.Type.Kind()); } } } } } return nil } func newDataSet(rows *sql.Rows) *DataSet { dataSet := new(DataSet) dataSet.init(rows) return dataSet }