Syl*_*sis 5 go structural-typing
在开始使用其他语言(如Scala和OCaml)进行结构化输入后,我开始研究Go,并且我正在尝试映射语言之间的一些惯用技术.请考虑以下类型
type CoordinatePoint struct {
x int
y int
// Other methods and fields that aren't relevant
}
type CartesianPoint struct {
x int
y int
// Other methods and fields that aren't relevant
}
Run Code Online (Sandbox Code Playgroud)
假设我们想编写一种方法,对这两种类型进行操作以计算它们的极坐标表示,func ConvertXYToPolar(point XYPoint) PolarPoint.如果CartesianPoint和CoordinatePoint类型定义了x和y字段的getter和setter方法,我们可以将它们定义XYPoint为与这些方法的公共接口,允许我们对这两种类型进行操作,但是就目前而言,接口不能声明字段,只能声明方法.
基于此,我有几个问题:
ConvertXYToPolar而不使用空接口类型作为参数并手动转换?我发现嵌入式类型的简单性,隐式接口满足性和基于接口的多态性是一种非常简单且吸引人的技术组合,可以提高代码的可重用性和可维护性,但禁止接口定义中的字段使得Go的结构类型化能力在某种程度上受限于我的观点.我错过了一个简单的解决方案?
通常的方法是使用组合:
type Point struct {
x int
y int
}
type CoordinatePoint struct {
Point
other stuff
}
type CartesianPoint struct {
Point
Other methods and fields that aren't relevant
}
Run Code Online (Sandbox Code Playgroud)
Go语法使得这个组合大多感觉像是在其他语言中的继承.你可以这样做:
cp := CoordinatePoint{}
cp.x = 3
log.Println(cp.x)
Run Code Online (Sandbox Code Playgroud)
你可以调用带有Pointas参数的函数
doAThingWithAPoint(cp.Point)
Run Code Online (Sandbox Code Playgroud)
要让您的点可以互换地传递,您必须定义一个接口
type Pointer interface {
GetPoint() *Point
}
func (cp CoordinatePoint) GetPoint() *Point {
return &cp.Point
}
Run Code Online (Sandbox Code Playgroud)
然后你就可以定义函数了Pointer:
func doSomethingWith(p Pointer) {
log.Println(p.GetPoint())
}
Run Code Online (Sandbox Code Playgroud)
另一种解决方案将基于定义一个接口上GetX,SetX,GetY和SetY,但我个人觉得这个方法比需要的更重,更详细.