I cracked my brain trying to make my code shorter and cleaner. The problem is in one function, that is working with different structs
, that implements
one interface
.
In some cases I need the model
variable to implement the structure (slice of rowModel's) ([]rowModel) and some times I need to use methods from interface. The code is not short, sorry for that. So I put main comments in the code below.
Here is interface:
type StatModel interface {
FilterData(Filter)
ClusterData(Filter)
CountDataForChart(string)[]ChartElement
GroupByTreeGroups(Filter)[]OrgPack
}
type StatRow interface {
Count( name string) float64
}
This interfaces are created for methods calls, and to make code shorter. But Interface cannot have fields or structure as Abstruct class in OOP. One of the models is here:
type NoaggModel []NoaggRow
type NoaggRow struct {
Date string
Hour int
Id_user int
Id_line float64
Id_region int
Id_tree_devision int
N_inb float64
N_out float64
N_hold float64
N_abandon float64
N_transfer float64
T_inb float64
T_out float64
T_hold float64
T_ring float64
T_acw float64
T_wait float64
}
type FcrModel []FcrRow
type FcrRow struct {
Date string
Hour int
Id_user int
Id_line float64
Id_region int
Id_tree_devision int
N_irr float64
N_inb float64
}
So , I'm reading from channel, and getting different structures, and trying to calculate everything correctly. How to make type assertion and method calls correctly in this case?
func receiveLightWork(org <-chan models.OrgPack, request ChartOptions) interface{} {
modelClusters := make(map[string][]models.OrgPack)
for orgPack := range org {
_, ok := modelClusters[orgPack.ModelName]
if ok {
model := modelClusters[orgPack.ModelName]
model = append(model, orgPack)
modelClusters[orgPack.ModelName] = model
}else {
var modelSlice []models.OrgPack
modelSlice = append(modelSlice, orgPack)
modelClusters[orgPack.ModelName] = modelSlice
}
}
output := make(map[string][]OrgStat)
for modelName, slice := range modelClusters {
//here I can't choose what to write
// model must be convertable to NoaggModel, that is []NoaggRow{}
// as others AcsiModel, FcrModel ...etc.
// Also model.ClusterData(customFilter) must be callable as it is in interface of common model
var model []interface{}
var rowModel interface{}
switch modelName {
case "noagg":
model = model.(models.NoaggModel)
rowModel = rowModel.(models.NoaggRow{})
case "acsi":
model = model.(models.AcsiModel)
rowModel = rowModel.(models.AcsiRow)
case "fcr24":
model = model.(models.FcrModel)
rowModel = rowModel.(models.FcrRow)
case "aic":
model = model.(models.AicModel)
rowModel = rowModel.(models.AicRow)
}
for _, el := range slice {
modelFields := reflect.ValueOf(&rowModel).Elem()
sliceFields := reflect.ValueOf(&el.SummorisedData).Elem()
fieldsTypes := modelFields.Type()
for i := 6; i < modelFields.NumField(); i++ {
fmt.Println(" model_field ", fieldsTypes.Field(i).Name )
modelField := modelFields.Field(i);
sliceField := sliceFields.Index(i-6) ;
modelField.Set(reflect.Value(sliceField));
}
id_line := sliceFields.Index(len(el.SummorisedData) - 1) ;
date := sliceFields.FieldByName("PackName");
modelFields.FieldByName("Id_line").Set(id_line)
modelFields.FieldByName("Date").Set(date)
// here append not works, because model is []interface{} and not []NoaggRow or others.
// Writes [non-interface type []interface {} on left]
model = append(model, rowModel)
}
customFilter := request.Filters
customFilter.Cluster = "clusterDay"
model.ClusterData(customFilter) // now here is unresolved Reference 'ClusterData'
for _, mod := range model {
for _, charts := range request.Charts {
var stats []OrgStat
for _, chart := range charts {
// now here is unresolved Reference 'Count'
stats = append(stats, OrgStat{Name:chart.Name, Value: mod.Count(mod, chart.Name)})
}
_, group_exist := output[mod.Date]
if group_exist {
inserted_stat := output[mod.Date]
output[mod.Date] = append(stats, inserted_stat...)
}else {
output[mod.Date] = stats }
}
}
}
return output
}
All help is very highly appreciated. I'll answer to each question on this topic if necessary. Thanks in advance!
Aucun commentaire:
Enregistrer un commentaire