如何设计具有可修改字段的结构?

时间:2015-06-11 21:56:01

标签: pointers go interface

我正在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结构以便能够修改其可移动物体? 我试图尝试接口指针,但我不是好主意......

感谢您的帮助!

1 个答案:

答案 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{}