避免在 Go 中编写过多的 getter 和 setter

我正在 Go 中实现一个消息传递系统。所以我有一个名为Msg. 该Msg接口定义了许多公共字段,例如源、目标、发送时间、接收时间等。我无法定义 s 的完整列表,Msg因为我希望库用户定义Msgs 的具体类型。


要提供具体的 类型Msg,用户需要实现大量的 getter 和 setter,这非常烦人。


我尝试过的一种解决方案是提供一个简单的基类,MsgBase并定义所有公共属性以及 getter 和 setter。对于 的每个具体类型Msg,我都嵌入了一个指向 的指针MsgBase。该解决方案有效。


但是,我想MsgBase在具体Msg类型中嵌入一个值版本。这是因为这样的Msgs 在执行过程中创建了太多次,动态分配 aMsgBase会增加垃圾收集开销。我真的希望所有的Msgs 都是静态分配的,因为它们由组件传递并且永远不应该共享。如果我使用 的值版本MsgBase,则无法使用 中定义的设置器MsgBase。


我想知道这个问题是否有任何简单的解决方案?


编辑:添加示例代码



type Msg interface {

    // Agent is another interface

    Src() Agent

    SetSrc(a Agent)

    Dst() Agent

    SetDst(a Agent)


    ... // A large number of properties

}


type MsgBase struct {

    src, dst Agent

    ... // Properties as private fields.

}


func (m MsgBase) Src() Agent {

    return m.src

}


func (m *MsgBase) SetSrc(a Agent) {

    m.src = a

}


... // Many other setters and getters for MsgBase



type SampleMsg struct {

    MsgBase // option1

    *MsgBase // option2

}


慕慕森
浏览 97回答 1
1回答

呼如林

请记住,Go 不像 Java 那样具有面向对象的继承。这听起来像是您正在尝试编写一个抽象基类来封装“消息”的所有部分;这不是真正典型的 Go 风格。您描述的字段是典型的消息元数据。您可以将此元数据封装在纯数据结构中。它不一定需要任何行为,也不一定需要 getter 和 setter 方法。type MessageMeta struct {  Source Agent  Destination Agent}更面向对象的方法是说一条消息有一个(可变的)元数据块和一个(不可变的,编码的)有效负载。import "encoding"type Message interface {  encoding.BinaryMarshaler // requires MarshalBinary()  Meta() *MessageMeta}type SomeMessage struct {  MessageMeta  Greeting string}func (m *SomeMessage) Meta() *MessageMeta {  return &m.MessageMeta}func (m *SomeMessage) MarshalBinary() ([]byte, error) {  return []byte(m.Greeting), nil}将这两件事分开传递的更程序化的方法也是合理的。在这种情况下,没有什么是“消息”的接口,您只需传递编码的有效负载;像这样的标准库接口encoding.BinaryMarshaler在这里很有意义。您可以将其包含在属于您的库的较低级别的界面中。func Deliver(meta *MessageMeta, payload []byte) error { ... }将一个翻译成另一个很容易func DeliverMessage(m Message) error {  payload, err := m.Payload()  if err != nil {    return err  }  meta := m.Meta()  return Deliver(meta, payload)}如果其中一个元数据字段是“交付于”,确保在整个链中传递一个指向元数据对象的指针可以让您更新原始对象中的该字段。我不会担心将垃圾收集作为首要考虑因素,除非是为了避免过度浪费,并在 GC 开始出现在配置文件中时检查对象分配。创建两个对象而不是一个对象在这里可能不会成为一个大问题。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go