我刚刚开始学习泛型.因此,我正在try 为我的定制数据库提供一个在一些协议消息上操作的驱动程序.
我想找到一种方法来进一步约束我的泛型类型,但将其作为指针,即确保(告诉编译器)约束E实现了另一个方法.
首先,我限制了db可以处理的实体.
type Entity interface {
pb.MsgA | pb.MsgB | pb.MsgC
}
然后,编写了一个描述数据库功能的通用接口,以便它可以被处理各自的Proto消息的不同服务使用:
type DB[E Entity] interface {
Get(...) (E, error)
List(...) ([]E, error)
...
}
到目前一切尚好.然而,我也希望这些实体在与数据库通信时被(反)序列化,以有线方式发送、克隆和合并.大概是这样的:
func Encode[E Entity](v *E) ([]byte, error) {
return proto.Marshal(v)
}
但是,上面的代码给出了以下错误:
cannot use val (variable of type *E) as type protoreflect.ProtoMessage in argument to proto.Marshal: *E does not implement protoreflect.ProtoMessage (type *E is pointer to type parameter, not type parameter)
问题是proto.Marshal
需要实体(*E)实现proto.Message
接口,即ProtoReflect()
方法,我的所有实体类型都实现了这一接口,但它不受约束,编译器无法推断.
我还试图将实体定义为:
type Entity interface {
*pb.MsgA | *pb.MsgB | *pb.MsgC
proto.Message
}
但是,除了需要执行一些额外的前瞻性操作来实例化我的Proto.Messages实体指针之外,这样做感觉并不正确.