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

现在我有一个使用并行算法计算统计数据的小应用程序。现在我在扩展部分功能时遇到了问题。我会尽快解释。应用程序建立在 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)”的名称在这个地方会有所不同。谁能帮我解决这个问题?


狐的传说
浏览 175回答 1
1回答

红颜莎娜

如果地图中的函数(即HOLD()、INB()、 等)不需要比 StatModel 接口提供的更多的模型访问权限,那么您的需求应该可以通过更改这些函数来接收 StatModel 而不是 NoaggRow 来实现:func HOLD(s StatModel) float64 {&nbsp; &nbsp; ...}那么你要添加的AcsiRow函数可以有相同的签名,statCount和Count可以改写如下:func statCount(model StatModel, f func(StatModel) float64) float64 {&nbsp; &nbsp; countedStat := f(model)&nbsp; &nbsp; return countedStat}func Count(model StatModel, name string) float64 {&nbsp; &nbsp; m := map[string]func(StatModel) float64 {&nbsp; &nbsp; &nbsp; &nbsp; "HOLD" : HOLD,&nbsp; &nbsp; &nbsp; &nbsp; "INB"&nbsp; : INB,&nbsp; &nbsp; &nbsp; &nbsp; "AHT"&nbsp; : AHT,&nbsp; &nbsp; &nbsp; &nbsp; "RING" : RING,&nbsp; &nbsp; &nbsp; &nbsp; "TALK" : TALK,&nbsp; &nbsp; &nbsp; &nbsp; "ACW"&nbsp; : ACW,&nbsp; &nbsp; &nbsp; &nbsp; "OCC"&nbsp; : OCC,&nbsp; &nbsp; &nbsp; &nbsp; // Map AcsiModel functions here, let's call them ACSIn here&nbsp; &nbsp; &nbsp; &nbsp; // (you mentioned that the names would be different, so&nbsp; &nbsp; &nbsp; &nbsp; // I assume they don't get in the way of the functions&nbsp; &nbsp; &nbsp; &nbsp; // above):&nbsp; &nbsp; &nbsp; &nbsp; "ACSI1": ACSI1,&nbsp; &nbsp; &nbsp; &nbsp; "ACSI2": ACSI2,&nbsp; &nbsp; &nbsp; &nbsp; "ACSI3": ACSI3,&nbsp; &nbsp; }&nbsp; &nbsp; countedStat := statCount(model, m[name])&nbsp; &nbsp; return countedStat}免责声明:这只是基于我在帖子中看到的内容的一个想法。我对 Revel 一无所知,因此也许我可能错过了一些由 Revel 上下文引起的重要细节,这些细节会阻止实施这种方法。根据评论更新:使用类型的断言,以使HOLD,OCC等功能,以访问结构特定的属性,像这样:func HOLD (s StatModel) float64 {&nbsp; &nbsp; noagg, ok := s.(NoaggRow) // typecast from StateModel to NoaggRow&nbsp; &nbsp; if !ok {&nbsp; &nbsp; &nbsp; &nbsp; // Looks like the caller did not pass a matching model/name pair into Count().&nbsp; &nbsp; &nbsp; &nbsp; // Error handling...&nbsp; &nbsp; }&nbsp; &nbsp; attr := noagg.AttributeSpecificToNoaggRow&nbsp; &nbsp; ...}这在运行时可能看起来有点危险,但如果调用者总是将匹配的模型/名称值对传递给 Count()(我假设它这样做了),则类型转换应该是安全的。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go