【发布时间】:2026-01-21 20:25:01
【问题描述】:
我有一个使用接口作为键的地图。该地图的定义如下MyMap map[Signature]Packets。接口是Signature,会有两个结构A和B实现这个接口。我也在使用msgp 来序列化这两个结构。
我的问题是msgp 自动生成使用指针作为函数接收器类型的方法,我认为这将使键Signature 接收指针。如果是这种情况,那么键每次都会不同,因为指针不同,即使基础值相同。因此,每次我都会创建一个新条目,而不是查找现有条目并对其进行修改。
我想知道:
- 有没有办法强制
msgp生成纯粹使用具体类型的函数接收器的方法?目前,我只能将MarshalMsg和UnmarshalMsg等自动生成方法的函数接收器修改为具体类型(A或B而不是*A或*B)。通过这样做,映射的键是A类型或B类型,并且映射MyMap工作正常。但是,我知道我不应该修改自动生成的代码。所以,我想知道是否有一种可接受的方式来做到这一点。 - 如果没有办法做 1.,有没有办法解决这个问题?我真的需要使用
msgp的地图键的一些多态特性。
更新 1(4 月 12 日): 感谢您分享您的想法并提供解决方案。以下是有关我的问题的一些详细信息。
- 背景是地图用于收集不同的网络事件。实现接口
Signature的两个结构是EventSignatureIPv4和EventSignatureIPv6
type EventSignatureIPv4 struct {
SourceIPv4 [4]byte
Port uint16
Traffic TrafficType
}
type EventSignatureIPv6 struct {
SourceIPv6 [16]byte
Port uint16
Traffic TrafficType
}
并且Signature 持有在 IPv4 和 IPv6 数据之间共享的通用方法。因此,本质上,我想在运行时收集和分组相应的 IPv4/v6 事件。地图的关键是识别同一个源,地图的价值是收集不同目的地的事件。
-
我正在使用的
msgp库是这个https://pkg.go.dev/github.com/tinylib/msgp@v1.1.5/msgp -
如果我错了,请纠正我。对于 Go 中的组合,如果方法集中的方法之一具有指针类型的函数接收器,那么实例只会是指针类型吗?所以在这里,就像我一样
func (z *EventSignatureIPv6) MarshalMsg(b []byte) (o []byte, err error) {
/* Auto-generated code */
}
每当我使用Signature 接收结构体EventSignatureIPv6 时,结构体只能是*EventSignatureIPv6 类型?
【问题讨论】:
-
您使用的是哪个
msgp库? -
@Sebastian 在 Golang 中,因为 Struct 是一种值类型,使用它们作为 Map 的 Key 是可能的。您是正确的,如果使用指针,您每次都会为相同的数据获得不同的密钥。因此,如果可能,您可以使用
*pointer语法获取指针的值,而不是直接保存指针。此外,如果您可以包含一些代码,则可以提出更好的解决方法。 -
@Christian 我使用的
msgp库是pkg.go.dev/github.com/tinylib/msgp@v1.1.5/msgp -
@SaiRaviTejaK 我认为这与您所说的情况不同。我已经更新了我的问题,请再看一下,看看您是否还有其他想法。
-
“地图的关键是识别相同的来源”——这在语义上并不合理,IMO。接口类型映射键的相等性甚至与数据包源的相等性意味着相同。由于实现接口的结构完全属于不同类型,因此您的 v4 和 v6 数据包将永远不会具有相同的哈希值。 See it for yourself,或对您的代码运行一些单元测试。如果您因为它们可能提供的某些分组/标识方法而考虑使用这些接口,请改用 that 来键入您的地图。
标签: go msgpack go-interface go-map