如何使用一个通用Map函数(Map2Vehicle)将2种不同的类型(汽车、自行车)Map到一种车辆类型。Car和Bicycle不能更改,因为它是自动生成的代码。
package main
import "fmt"
func main() {
c := Car{Name: "MyCar", Wheels: CarWheels{Count: 4}}
b := Bicycle{Name: "MyBicycle", Wheels: BicycleWheels{Count: 2}}
v1 := Map2Vehicle(&c)
v2 := Map2Vehicle(&b)
fmt.Println(v1.Name, v2.Name)
}
// ---------------- Car
type Car struct {
Name string
Wheels CarWheels
}
type CarWheels struct {
Count int
}
func (c *Car) GetName() string { return c.Name }
func (c *Car) GetWheels() CarWheels { return c.Wheels }
func (w *CarWheels) GetCount() int { return w.Count }
// ---------------- Bicycle
type Bicycle struct {
Name string
Wheels BicycleWheels
}
type BicycleWheels struct {
Count int
}
func (b *Bicycle) GetName() string { return b.Name }
func (b *Bicycle) GetWheels() BicycleWheels { return b.Wheels }
func (w *BicycleWheels) GetCount() int { return w.Count }
// ---------------- Vehicle
type wheels interface {
GetCount() int
}
type vehicle[T wheels] interface {
GetName() string
GetWheels() T
}
type Vehicle struct {
Name string
}
func Map2Vehicle[T vehicle[wheels]](v T) *Vehicle {
return &Vehicle{
Name: fmt.Sprintf("%s with %d wheels", v.GetName(), v.GetWheels().GetCount()),
}
}
字符串
错误:代码不工作:
cmd/tmp/tmp.go:8:19: *Car does not satisfy vehicle[wheels] (wrong type for method GetWheels)
have GetWheels() CarWheels
want GetWheels() wheels
cmd/tmp/tmp.go:9:19: *Bicycle does not satisfy vehicle[wheels] (wrong type for method GetWheels)
have GetWheels() BicycleWheels
want GetWheels() wheels
型
预期输出:
MyCar with 4 wheels MyBicycle with 2 wheels
型
有什么想法可以解决golang泛型的问题吗?
3条答案
按热度按时间tp5buhyn1#
首先:
CarWheels
和BicycleWheels
没有实现wheels
接口。这是因为你的GetCount
方法使用了指针接收器:字符串
因此,
*CarWheels
和*BicycleWheels
(指向结构体的指针)实现了wheels
接口,但结构体本身没有。我只是简单地删除指针接收器,因为这些结构非常小(实际上只有int
s),并且没有必要使用指针“装箱”它们(这样做只会产生开销):型
或者,如果你的真实的结构体更大,你当然也可以让你的
GetWheels
方法返回 * 指向轮子的指针 * 而不是 * 轮子本身 *。第二:你的函数有一个签名
func Map2Vehicle[T vehicle[wheels]](v T) *Vehicle
。这意味着v
必须是vehicle
,其中GetWheels
方法的返回类型为wheels
,而不是任何实现wheels
的返回类型。这个问题的解决方案是让GetWheels
函数返回抽象的wheels
类型,而不是特定的类型:型
如果这样做,代码将按预期运行。
或者,如果你想保留特定的类型,你必须让轮子成为函数的第二个泛型参数:
型
Go将无法推断
W
(似乎泛型类型推断不会嵌套),所以现在必须在调用站点明确车轮的类型(但它仍然可以推断车辆的类型):型
如果要重构它,我会通过让
GetWheels
方法返回wheels
接口类型来完全消除泛型;那么Map2Vehicle
可以在任何vehicle
上操作,并且vehicle
不需要是泛型的:型
dly7yett2#
为什么不创建两个不同类型的值,Car和Bicycle,然后使用
Map2Vehicle
函数将每个值Map到Vehicle类型?Playground链接:https://play.golang.com/p/lPFoFEsjIeD
字符串
输出:
nue99wik3#
你试图在Go语言中使用泛型将不同的类型(
Car
和Bicycle
)Map到一个公共的Vehicle
类型。但是,您遇到了一个错误,因为类型Car
和Bicycle
对于GetWheels()
方法具有不同的实现。要解决这个问题,您可以修改代码,在
Car
和Bicycle
结构中为Wheels
字段使用接口而不是具体类型。通过这样做,您可以为CarWheels
和BicycleWheels
定义一个满足wheels
接口的GetWheels()
实现。下面是代码的更新版本:字符串
现在,代码应该编译并生成您期望的输出:
型