我有几个自定义类型需要以相同的方式进行处理.这似乎是泛型的完美用途.在这个过程中,我需要调用类型实例上的方法,这些方法返回相同类型的不同实例,然后我需要调用那些返回的实例上的方法,这是我无法工作的.出于这个问题的目的,我构造了一组简单得多的类型和一个过程,它例证了我遇到的问题.
下面是一个没有泛型的工作示例,它显示了类型(Circle
和Square
)和一个过程(.Bigger().Smaller()
),稍后我将try 将其抽象为泛型函数(online demo):
package main
import (
"fmt"
)
type Circle struct{ r float64 }
func NewCircle(r float64) *Circle { return &Circle{r: r} }
func (c *Circle) Radius() float64 { return c.r }
func (c *Circle) Bigger() *Circle { return &Circle{r: c.r + 1} }
func (c *Circle) Smaller() *Circle { return &Circle{r: c.r - 1} }
type Square struct{ s float64 }
func NewSquare(s float64) *Square { return &Square{s: s} }
func (s *Square) Side() float64 { return s.s }
func (s1 *Square) Bigger() *Square { return &Square{s: s1.s + 1} }
func (s1 *Square) Smaller() *Square { return &Square{s: s1.s - 1} }
func main() {
fmt.Println(NewCircle(3).Bigger().Smaller().Radius()) // prints 3
fmt.Println(NewSquare(6).Bigger().Smaller().Side()) // prints 6
}
创建泛型函数的第一件事是定义类型约束:
type ShapeType interface {
*Circle | *Square
}
我将把ShapeType
传递给process
方法,并且我需要能够调用ShapeType
实例上的方法,因此我需要定义另一个类型约束来指定可以在ShapeType
上调用的方法:
type Shape[ST ShapeType] interface {
Bigger() ST
Smaller() ST
}
有了这些,我可以编写一个process
方法(online demo):
func process[ST ShapeType](s Shape[ST]) ST {
return s.Bigger().Smaller()
}
然而,这无法编译,因为s.Bigger()
的返回值是ST
,而不是Shape[ST]
,所以Go不知道它可以在返回值s.Bigger()
上调用Smaller()
.用Go的话说:
S.Bigger().Smaller未定义(类型ST没有更小的字段或方法)
如果Bigger()
和Smaller()
没有返回它们的接收器类型的实例,我可以这样写:
type Shape interface {
*Circle | *Square
Bigger()
Smaller()
}
func process[S Shape](x S) S {
x.Bigger().Smaller()
return x // I guess we wouldn't even have to return x, but just for example's sake
}
相反,我需要写下:
type Shape interface {
*Circle | *Square
Bigger() Shape
Smaller() Shape
}
而且,围棋似乎不喜欢自引用类型的约束.
如果可以将具体类型断言/转换为它所遵循的接口,那么我可以让它工作,但似乎不可能做到这一点(online demo):
func process[ST ShapeType](s Shape[ST]) ST {
s1 := s.Bigger()
s2 := s1.(Shape[ST]) // go is not happy here
return s2.Smaller()
}
对于这一点,Go说:
无法对类型参数值S1(由ShapeType约束的ST类型变量)使用类型断言
我不知道还能试什么.
是否可以使用泛型来处理这类类型?如果是这样的话,是如何做到的呢?