我有两个非常相似的结构,我想创建可以对它们进行操作的函数。
我还有两种类型,它们被定义为这两个结构的切片。这个例子被简化了。事实上,我在这些结构类型上也有函数接收器。
我不能让泛型工作,主要是因为两个原因。我的切片类型似乎可以处理一些操作,但不是全部。例如,它可以与len()
函数一起使用,但不能使用括号对其进行索引:[]
。
第二个问题是,我不知道如何从切片类型中提取结构类型。例如,如果我想迭代切片并将值传递给函数,我该如何键入该函数来接受切片包含的结构?
我可以不通过go中的泛型来实现这一点吗?如果是这样的话,实现这一点的惯用方法是什么?
以下是我试图实现的一个简化示例:
package main
import (
"fmt"
"math"
)
type Year struct {
Revenue int
Earnings int
}
type Years []Year
type Quarter struct {
Revenue int
Earnings int
}
type Quarters []Quarter
func revenueGrowth[T Year | Quarter](current, previous T) {
return (current.Revenue - previous.Revenue) / math.Abs(previous.Revenue) // ERROR: current.Revenue undefined (type T has no field or method Revenue)
}
func earningsGrowth[T Year | Quarter](current, previous T) {
return (current.Earnings - previous.Earnings) / math.Abs(previous.Earnings) // ERROR: current.Revenue undefined (type T has no field or method Revenue)
}
// printGrowthPerYear prints the revenue growth for each year
func growthPerYear[T Years | Quarters, U Year | Quarter](reports T, selector func(current, previous U) float64) float64 {
var sum float64
for i := 0; i < len(reports)-1; i++ {
sum = sum + selector(reports[i], reports[i+1]) // ERROR: invalid operation: cannot index reports (variable of type T constrained by Years|Quarters)
}
return sum
}
func printAverageGrowthOverYears[T Years | Quarters, U Year | Quarter](estimates, reports T, numOfYears int, selector func(current, previous U) float64) {
combinedReportsAndEstimates := T{} // ERROR: invalid composite literal type T
// Start by adding estimates to the combined slice
for i := 0; i < len(numOfYears); i++ {
combinedReportsAndEstimates := append(combinedReportsAndEstimates, estimates[i]) // ERROR: invalid operation: cannot index estimates (variable of type T constrained by Years|Quarters)
}
// Backfill with the latest reports
numOfReportsToBackfillWith := numOfYears - len(combinedReportsAndEstimates)
for i := 0; i < numOfReportsToBackfillWith; i++ {
combinedReportsAndEstimates[i] = reports[i] // ERROR: invalid operation: cannot index reports (variable of type T constrained by Years|Quarters)
}
growth := growthPerYear(combinedReportsAndEstimates, selector)
fmt.Println(growth / float64(numOfYears))
}
func main() {
years := Years{
{Revenue: 1000, Earnings: 100},
{Revenue: 750, Earnings: 75},
{Revenue: 500, Earnings: 50},
{Revenue: 250, Earnings: 25},
}
estimatedYears := Years{
{Revenue: 1250, Earnings: 125},
}
fmt.Println("========Years==========")
printAverageGrowthOverYears(estimatedYears, years, revenueGrowth[Year], 4) // ERROR: cannot infer U
printAverageGrowthOverYears(estimatedYears, years, earningsGrowth[Year], 4) // ERROR: cannot infer U
quarters := Quarters{
{Revenue: 100, Earnings: 10},
{Revenue: 75, Earnings: 7},
{Revenue: 50, Earnings: 5},
{Revenue: 25, Earnings: 2},
}
estimatedQuarters := Quarters{
{Revenue: 125, Earnings: 12},
}
fmt.Println("========Quarters==========")
printAverageGrowthOverYears(estimatedQuarters, quarters, revenueGrowth[Quarter], 2) // ERROR: cannot infer U
printAverageGrowthOverYears(estimatedQuarters, quarters, earningsGrowth[Quarter], 2) // ERROR: cannot infer U
}
我已经尝试使这些函数通用于Year
、Years
、Quarter
和Quarters
。
你有很多错误,我试着弄清楚你的意思是
在函数printAverageGrowthOverYears
中,我不知道的真正目标是什么
所以我Guess It
package main
import (
"fmt"
"math"
"reflect"
)
type M interface {
GetRevenue() float64
GetEarnings() float64
}
type Year struct {
Revenue float64
Earnings float64
OtherThing string
}
type Quarter struct {
Revenue float64
Earnings float64
AnotherThing string
}
func (y Year) GetRevenue() float64 {
return y.Revenue
}
func (q Quarter) GetRevenue() float64 {
return q.Earnings
}
func (y Year) GetEarnings() float64 {
return y.Revenue
}
func (q Quarter) GetEarnings() float64 {
return q.Earnings
}
type Years []Year
type Quarters []Quarter
func revenueGrowth(current, previous M) float64 {
return (current.GetRevenue() - previous.GetRevenue()) / math.Abs(previous.GetRevenue())
}
func earningsGrowth(current, previous M) float64 {
return (current.GetEarnings() - previous.GetEarnings()) / math.Abs(previous.GetEarnings())
}
// printGrowthPerYear prints the revenue growth for each year
func growthPerYear(reports []interface{}, selector func(current, previous M) float64) float64 {
var sum float64
for i := 0; i < len(reports)-1; i++ {
sum = sum + selector(reports[i].(M), reports[i+1].(M))
}
return sum
}
func min(a int, b int) int {
if a < b {
return a
}
return b
}
func printAverageGrowthOverYears(estimates interface{}, reports interface{}, numOfYears int, selector func(current, previous M) float64) {
estimates_l := reflect.ValueOf(estimates)
combinedReportsAndEstimates := make([]interface{}, 0)
for i := 0; i < min(estimates_l.Len(), numOfYears); i++ {
combinedReportsAndEstimates = append(combinedReportsAndEstimates, estimates_l.Index(i).Interface().(M))
}
numOfReportsToBackfillWith := numOfYears - len(combinedReportsAndEstimates)
reports_l := reflect.ValueOf(reports)
numOfReportsToBackfillWith = min(reports_l.Len(), numOfReportsToBackfillWith)
//Here I Guess You Mean This?
for i := 0; i < numOfReportsToBackfillWith; i++ {
combinedReportsAndEstimates = append(combinedReportsAndEstimates, reports_l.Index(i).Interface().(M))
}
growth := growthPerYear(combinedReportsAndEstimates, selector)
fmt.Println(growth / float64(numOfYears))
}
func main() {
years := Years{
{Revenue: 1000, Earnings: 100},
{Revenue: 750, Earnings: 75},
{Revenue: 500, Earnings: 50},
{Revenue: 250, Earnings: 25},
}
estimatedYears := Years{
{Revenue: 1250, Earnings: 125},
}
fmt.Println("========Years==========")
printAverageGrowthOverYears(estimatedYears, years, 4, revenueGrowth) // ERROR: cannot infer U
printAverageGrowthOverYears(estimatedYears, years, 4, earningsGrowth) // ERROR: cannot infer U
quarters := Quarters{
{Revenue: 100, Earnings: 10},
{Revenue: 75, Earnings: 7},
{Revenue: 50, Earnings: 5},
{Revenue: 25, Earnings: 2},
}
estimatedQuarters := Quarters{
{Revenue: 125, Earnings: 12},
}
fmt.Println("========Quarters==========")
printAverageGrowthOverYears(estimatedQuarters, quarters, 2, revenueGrowth) // ERROR: cannot infer U
printAverageGrowthOverYears(estimatedQuarters, quarters, 2, earningsGrowth) // ERROR: cannot infer U
}
只是对"J Chen";,您的问题将在这个GitHub问题链接中讨论。我强烈建议你阅读《问答》的全文,深入了解你的问题和可能的解决方案
您可以做的另一件事是使用结构嵌入并创建一个只有两个相关字段的父。在这种情况下,您应该能够在不使用泛型的情况下实现所需的功能
如果您想坚持泛型,只需在其类型集中创建一个具有两个getter方法的接口,使用它来强制传入的类型满足约束,并在函数体中调用必须由特定结构实现的getter方法
如果您还需要帮助,请告诉我,谢谢!