泛型结构体中基于指针类型创建已初始化指针对象的问题
问题分析
你的泛型参数Receive被实例化为指针类型(比如*set.Request),而new(Receive)会创建一个指向该指针类型的指针(即**set.Request),这和方法返回值类型Receive(即*set.Request)类型不匹配,导致编译错误。
解决方案
方案一:调整泛型参数为非指针类型(推荐)
修改TypedConnection的定义和方法,让泛型参数接收非指针的proto消息类型,内部自动处理指针逻辑:
import "google.golang.org/protobuf/proto" type TypedConnection[Receive, Send any] struct { raw_connection Connection } func MakeTypedConnection[Receive, Send proto.Message](raw_connection Connection) TypedConnection[Receive, Send] { return TypedConnection[Receive, Send]{ raw_connection: raw_connection, } } func (this *TypedConnection[Receive, Send]) Receive() (message *Receive, err error) { var data Data data, err = this.raw_connection.Receive() if err != nil { return } bytes, err := data.Bytes() if err != nil { return } message = new(Receive) err = proto.Unmarshal(bytes, message) return }
使用时传入非指针类型即可:
stream := transfer.MakeTypedStream[set.Request, set.Response](raw_stream)
这种方式避免了反射,符合proto消息的常规使用习惯,new(Receive)创建的*Receive类型完全匹配返回值要求,同时满足proto.Unmarshal的参数约束。
方案二:保留指针泛型参数,用反射创建实例
如果不想修改现有调用方式,可通过反射创建正确的指针实例:
import ( "google.golang.org/protobuf/proto" "reflect" ) type TypedConnection[Receive, Send proto.Message] struct { raw_connection Connection } func MakeTypedConnection[Receive, Send proto.Message](raw_connection Connection) TypedConnection[Receive, Send] { return TypedConnection[Receive, Send]{ raw_connection: raw_connection, } } func (this *TypedConnection[Receive, Send]) Receive() (message Receive, err error) { var data Data data, err = this.raw_connection.Receive() if err != nil { return } bytes, err := data.Bytes() if err != nil { return } // 反射获取指针的元素类型,再创建对应指针实例 msgType := reflect.TypeOf(message).Elem() message = reflect.New(msgType).Interface().(Receive) err = proto.Unmarshal(bytes, message) return }
该方案无需修改现有调用代码,反射操作在当前泛型约束下是安全可控的。
内容的提问来源于stack exchange,提问作者Nufun
相关产品推荐
相关产品推荐

