想象一下,有人初始化了一个rpc 客户端,client, _ := rpc.Dial('tcp', 'example.com:port')
并且只为您提供了 rpc 客户端实例。出于某种原因,您想example.com
从客户端实例中获取地址。但是,由于客户端类型是高度抽象的,您无法直接获取net.Conn
服务于方法的实例RemoteAddr()
。在这种情况下,反射包可能会有所帮助。
让我们从以下尝试开始:
func getRemoteAddr(client *rpc.Client) net.Addr {
codec := reflect.Indirect(rpclient).FieldByName("codec")
connV := codec.FieldByName("rwc")
conn := connV.Interface().(net.Conn)
return conn.RemoteAddr()
}
然而,第二行立即跳出一个错误:
panic: reflect: call of reflect.Value.FieldByName on interface Value
这是合理的,因为它codec被声明为类型ClientCodec,它只是一个具有四个方法签名的接口。但是,从代码中,我们知道详细类型codec可能是未导出的 struct gobClientCodec。不幸的是,Go 编译器不够聪明,无法深入追踪并找出实际类型。因此,反射包有没有办法告诉编译器我对codec未导出的类型有信心gobClientCodec?如果这是不可能的,我可能不得不计算地址偏移量并使用不安全的指针,这是最后的选择。
PSType()反射方法中的默认方法不会像codec声明的那样工作,ClientCodec并通过在方法中传递gobClientCodec结构的地址来初始化,NewClient如下所示:
func NewClient(conn io.ReadWriteCloser) *Client {
encBuf := bufio.NewWriter(conn)
client := &gobClientCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(encBuf), encBuf}
return NewClientWithCodec(client)
}
此外,reflect.TypeOf(rpc.gobClientCodec)不会像编译器拒绝未导出的类型使用一样工作。
元芳怎么了
相关分类