Architecture 找出go对象组成的困难

Architecture 找出go对象组成的困难,architecture,go,object-composition,Architecture,Go,Object Composition,我目前正在使用go来实现一个游戏服务器,因为它有很棒的并发原语。这一切都很容易实现,并且工作非常可靠。不过,我主要来自Java背景,很难忘记Java的类型层次结构。我需要有一个游戏对象的集合,这些对象都共享类似的数据结构,如位置、速度等,但它们在更新方法中可能有不同的行为,或者有允许不同功能的特殊字段。最初,我有一个包含所有共享数据的结构,每个自定义类型都将嵌入该结构。问题在于使用数据结构进行组织。我使用四叉树来通知客户端附近对象的状态。通过这种方式,我可以向树传递一个指向每个游戏对象的嵌入式结

我目前正在使用go来实现一个游戏服务器,因为它有很棒的并发原语。这一切都很容易实现,并且工作非常可靠。不过,我主要来自Java背景,很难忘记Java的类型层次结构。我需要有一个游戏对象的集合,这些对象都共享类似的数据结构,如位置、速度等,但它们在更新方法中可能有不同的行为,或者有允许不同功能的特殊字段。最初,我有一个包含所有共享数据的结构,每个自定义类型都将嵌入该结构。问题在于使用数据结构进行组织。我使用四叉树来通知客户端附近对象的状态。通过这种方式,我可以向树传递一个指向每个游戏对象的嵌入式结构的指针,并且一切正常

问题是,一旦查询四叉树,我就无法访问包含的类型。那么比如说,

type GameObject struct {
    Position Point
    Velocity Point
    ID int32
}

type Client struct {
    GameObject
    conn net.Conn
    // other fields
}
现在,如果我想向附近的玩家更新一个对象的状态,我会查询四叉树,但是现在有办法确定这个游戏对象是否真的是一个客户端,并且没有办法访问它的连接来发送数据包

从Java开始,我习惯于创建一个基类并为客户机对其进行子类化,等等。然后我可以使用
instanceof
来确定哪些类需要特殊处理,并相应地转换它们以访问自定义功能。我想我可以做如下的事情:

type GameObject interface {
    Position() Point
    Velocity() Point
    ID() int32
}

type Client struct {
    pos Point
    vel Point
    id int32
    conn net.Conn
    // other fields
}

func (c *Client) Position() Point {
    return c.pos
}

func (c *Client) Velocity() Point {
    return c.vel
}

func (c *Client) ID() int32 {
    return c.id
}

使用这种方法,我可以使用类型断言来隔离客户端,但这将导致实现其他游戏对象的大量重复代码。我想在围棋中有一种更惯用的方式来做类似的事情,我很感激能得到的任何帮助。如果是这样的话,也许有人能帮助我理解这个设计背后的原因。

如果不了解更多关于问题和您的限制,很难回答这个问题,但这里有三个想法

首先,也许你可以在四叉树中存储一个复合类型,而不仅仅是游戏对象指针

type QuadTreeEntry struct {
   GameOb *GameObject
   Entity interface{}
}
“实体”将是一个*客户机,以及四叉树中的任何其他内容

第二,如果你需要四叉树中所有的游戏对象,你可以考虑。也许这样更好

type QuadTreeEntry struct {
    Position Point
    Entity interface{}
}
这有一个很好的效果,即删除一个间接寻址以获取四叉树代码中的位置,并且由于四叉树不与原始实体共享位置数据,因此很难意外地使您的四叉树无效

第三,如果效率不太重要,你可以这样做:

type GameObjectGetter interface {
    GetGameObject() *GameObject
}

func (c *Client) GetGameObject() *GameObject {
    return &c.GameObject
}
因此,四叉树中的所有内容都将是GameObjectGetter