我正在Go中编写一个简单的游戏并遇到一些问题。我的,截止,代码看起来像这样:
package main
import "fmt"
type Location struct {
X int
Y int
}
type Car struct {
MaxSpeed int
Loc Location
}
func (car Car) SetLocation(loc Location) {
car.Loc = loc
}
func (car Car) GetLocation() Location {
return car.Loc
}
type Bike struct {
GearsNum int
Loc Location
}
func (bike Bike) SetLocation(loc Location) {
bike.Loc = loc
}
func (bike Bike) GetLocation() Location {
return bike.Loc
}
type Movable interface {
GetLocation() Location
SetLocation(Location)
}
type Fleet struct {
vehicles []Movable
}
func (fleet *Fleet) AddVehicles(v ...Movable) {
for _, x := range(v) {
fleet.vehicles = append(fleet.vehicles, x)
}
}
func (fleet *Fleet) WherTheyAre() {
for _, v := range(fleet.vehicles) {
fmt.Println(v.GetLocation())
}
}
func main() {
myCar := Car{MaxSpeed: 200, Loc: Location{12, 34}}
myBike := Bike{GearsNum: 11, Loc: Location{1, 1}}
myFleet := Fleet{}
myFleet.AddVehicles(myCar)
myFleet.AddVehicles(myBike)
myFleet.WherTheyAre()
myCar.SetLocation(Location{0,0})
myFleet.WherTheyAre()
}
假设汽车和自行车是非常大的结构,我不想复制。我应该如何设计代码以便能够修改作为舰队一部分的汽车的位置?换句话说,如何设计Fleet结构以便能够修改其可移动物体? 我试图尝试接口指针,但我不是好主意......
感谢您的帮助!
答案 0 :(得分:1)
问题在于您已使用值接收器定义了该方法。当您在接收器上调用方法时,接收类型实际上是作为参数传递的,在这种情况下是按值并且您正在修改该副本。
On throw 1 we rolled:
[5, 4, 4]
On throw 2 we rolled:
[4, 4, 2]
On throw 3 we rolled:
[6, 6, 6]
[[5, 4, 4], [4, 4, 2], [6, 6, 6]]
您必须以不同的方式声明您的类型,或者使用func (bike Bike) SetLocation(loc Location) {
bike.Loc = loc // modifies local copy of Bike
}
func (bike *Bike) SetLocation(loc Location) {
bike.Loc = loc // modifies the referenced bike
}
运算符来调用这些方法,因为您的主要类型中包含值类型。我的偏好是几乎在所有情况下都使用这种语法&
。如果我有一个方便的启动方法或使用值类型的非常具体的原因(这是非常罕见的),我只会放弃它。
但基本上,你不能让setter使用值类型的接收器。如果要将这些结构用作值类型,我建议导出字段,以便可以在不使用getter或setter的情况下访问它们。另外,就风格而言,除非你真的抽象出一些逻辑,否则我会很高兴看到使用getter和setter。如果你要提供一个直接分配传入所述字段的值的setter,那么不导出字段是没有意义的。此外,没有仔细查看,但您要导出结构中的所有字段,因此您的安装程序无用,大多数程序员只会bike := &Bike{}