现在我有一个用于使用并行算法计算统计数据的小应用程序。 现在我在扩展某些功能方面遇到了问题。我会尽快解释。 App建立在狂欢框架之上。 " stat"的一个动作控制器接收传入的POST json。解析它。并为任务和结果生成两个通道(goroutines)。所有这一切都像一个魅力。但我对模特有麻烦。我编写的代码能够线性扩展模型数量,但目前只有一个在工作中。
并非所有方法都采用这种扩展。
在代码的某些部分,我有这个:
for t := range in {
for sourceName, charts := range t.Request.Charts {
var cacheData []byte
var deserializedData models.StatModel
//determine the model type
switch sourceName {
case "noagg":
deserializedData = new(models.NoaggModel)
case "acsi":
deserializedData = new(models.AcsiModel)
}
cache_err := cache.Get(string(string(sourceName) + "_" + string(t.Date)), &cacheData);
if cache_err != nil {
panic("the cache is empty")
}
marshal_error := json.Unmarshal([]byte(cacheData), &deserializedData)
if marshal_error == nil {
}
deserializedData.FilterData(t.Request.Filters)
deserializedData.ClusterData(t.Request.Filters)
w := Work{}
for _, chart := range charts {
countedData := ChartElements{}
if marshal_error == nil {
countedData = deserializedData.CountDataForChart(string(chart.Name))
}else {
panic("some is bad")
}
w.Name, w.Data = chart.Name, countedData
out <- w
}
}
}
Noagg模型和Asci模型正在实现&#34; stat&#34;型号:
type StatModel interface {
FilterData(Filter)
ClusterData(Filter)
CountDataForChart(string)[]ChartElement
GroupByTreeGroups(Filter)[]OrgPack
}
但是现在我必须添加一些具有相同界面的新模型,但是有代码,我无法扩展。我无法记住如何做到这一点..
func statCount(model NoaggRow, f func(NoaggRow) float64) float64 {
countedStat := f(model)
return countedStat
}
func Count(model NoaggRow, name string) float64{
m := map[string]func(NoaggRow) float64 {
"HOLD" : HOLD,
"INB" : INB,
"AHT" : AHT,
"RING" : RING,
"TALK" : TALK,
"ACW" : ACW,
"OCC" : OCC,
}
countedStat := statCount(model, m[name])
return countedStat
}
我对ASCI模型所需的方法相同。对于AcsiRow而不是NoaggRow。如何使这个输入参数类型动态或如何使所有模型的方法共同。只有数组和名称&#34; map [string] func(...... Row)&#34;在这个地方会有所不同。任何人都可以帮我解决这个问题吗?
答案 0 :(得分:1)
如果地图中的函数(即HOLD()
,INB()
等)不需要比StatModel接口提供的模型更多的访问权限,那么您的要求应该可以通过更改这些来实现函数接收StatModel而不是NoaggRow:
func HOLD(s StatModel) float64 {
...
}
然后,您要添加的AcsiRow函数可以具有相同的签名,statCount和Count可以按如下方式重写:
func statCount(model StatModel, f func(StatModel) float64) float64 {
countedStat := f(model)
return countedStat
}
func Count(model StatModel, name string) float64 {
m := map[string]func(StatModel) float64 {
"HOLD" : HOLD,
"INB" : INB,
"AHT" : AHT,
"RING" : RING,
"TALK" : TALK,
"ACW" : ACW,
"OCC" : OCC,
// Map AcsiModel functions here, let's call them ACSIn here
// (you mentioned that the names would be different, so
// I assume they don't get in the way of the functions
// above):
"ACSI1": ACSI1,
"ACSI2": ACSI2,
"ACSI3": ACSI3,
}
countedStat := statCount(model, m[name])
return countedStat
}
免责声明:这只是一个基于我在帖子中看到的内容的想法。我对Revel一无所知,也许我可能错过了Revel上下文引起的一些重要细节,这些细节会妨碍实现这种方法。
根据评论更新:
使用type assertions启用HOLD
,OCC
等功能来访问特定于结构的属性,如下所示:
func HOLD (s StatModel) float64 {
noagg, ok := s.(NoaggRow) // typecast from StateModel to NoaggRow
if !ok {
// Looks like the caller did not pass a matching model/name pair into Count().
// Error handling...
}
attr := noagg.AttributeSpecificToNoaggRow
...
}
这可能在运行时看起来有点风险,但如果调用者总是将匹配的模型/名称值对传递给Count()(我假设它这样做),则类型转换应该是安全的。