为了账号安全,请及时绑定邮箱和手机立即绑定

GO:具有不同类型输入的模型(或接口)函数

GO:具有不同类型输入的模型(或接口)函数

Go
狐的传说 2022-01-04 21:19:43
现在我有一个使用并行算法计算统计数据的小应用程序。现在我在扩展部分功能时遇到了问题。我会尽快解释。应用程序建立在 revel 框架上。“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 模型正在实现“stat”模型的相同接口: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}与 ASCI 模型所需的方法相同。对于 AcsiRow 而不是 NoaggRow。如何使此输入参数类型动态或如何使所有模型的方法通用。只有数组和“map[string]func(......Row)”的名称在这个地方会有所不同。谁能帮我解决这个问题?
查看完整描述

1 回答

?
红颜莎娜

TA贡献1842条经验 获得超12个赞

如果地图中的函数(即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 上下文引起的重要细节,这些细节会阻止实施这种方法。


根据评论更新:


使用类型的断言,以使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()(我假设它这样做了),则类型转换应该是安全的。



查看完整回答
反对 回复 2022-01-04
  • 1 回答
  • 0 关注
  • 174 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号